1/*
2 * -------------------------------------------------------------
3 *
4 * Module: sem_post_multiple.c
5 *
6 * Purpose:
7 *	Semaphores aren't actually part of the PThreads standard.
8 *	They are defined by the POSIX Standard:
9 *
10 *		POSIX 1003.1b-1993	(POSIX.1b)
11 *
12 * -------------------------------------------------------------
13 *
14 * --------------------------------------------------------------------------
15 *
16 *      Pthreads-win32 - POSIX Threads Library for Win32
17 *      Copyright(C) 1998 John E. Bossom
18 *      Copyright(C) 1999,2005 Pthreads-win32 contributors
19 *
20 *      Contact Email: rpj@callisto.canberra.edu.au
21 *
22 *      The current list of contributors is contained
23 *      in the file CONTRIBUTORS included with the source
24 *      code distribution. The list can also be seen at the
25 *      following World Wide Web location:
26 *      http://sources.redhat.com/pthreads-win32/contributors.html
27 *
28 *      This library is free software; you can redistribute it and/or
29 *      modify it under the terms of the GNU Lesser General Public
30 *      License as published by the Free Software Foundation; either
31 *      version 2 of the License, or (at your option) any later version.
32 *
33 *      This library is distributed in the hope that it will be useful,
34 *      but WITHOUT ANY WARRANTY; without even the implied warranty of
35 *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
36 *      Lesser General Public License for more details.
37 *
38 *      You should have received a copy of the GNU Lesser General Public
39 *      License along with this library in the file COPYING.LIB;
40 *      if not, write to the Free Software Foundation, Inc.,
41 *      59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
42 */
43
44#include "pthread.h"
45#include "semaphore.h"
46#include "implement.h"
47
48
49int
50sem_post_multiple (sem_t * sem, int count)
51     /*
52      * ------------------------------------------------------
53      * DOCPUBLIC
54      *      This function posts multiple wakeups to a semaphore.
55      *
56      * PARAMETERS
57      *      sem
58      *              pointer to an instance of sem_t
59      *
60      *      count
61      *              counter, must be greater than zero.
62      *
63      * DESCRIPTION
64      *      This function posts multiple wakeups to a semaphore. If there
65      *      are waiting threads (or processes), n <= count are awakened;
66      *      the semaphore value is incremented by count - n.
67      *
68      * RESULTS
69      *              0               successfully posted semaphore,
70      *              -1              failed, error in errno
71      * ERRNO
72      *              EINVAL          'sem' is not a valid semaphore
73      *                              or count is less than or equal to zero.
74      *              ERANGE          semaphore count is too big
75      *
76      * ------------------------------------------------------
77      */
78{
79  int result = 0;
80  long waiters;
81  sem_t s = *sem;
82
83  if (s == NULL || count <= 0)
84    {
85      result = EINVAL;
86    }
87  else if ((result = pthread_mutex_lock (&s->lock)) == 0)
88    {
89      /* See sem_destroy.c
90       */
91      if (*sem == NULL)
92        {
93          (void) pthread_mutex_unlock (&s->lock);
94          result = EINVAL;
95          return -1;
96        }
97
98      if (s->value <= (SEM_VALUE_MAX - count))
99	{
100	  waiters = -s->value;
101	  s->value += count;
102	  if (waiters > 0)
103	    {
104#if defined(NEED_SEM)
105	      if (SetEvent(s->sem))
106		{
107		  waiters--;
108		  s->leftToUnblock += count - 1;
109		  if (s->leftToUnblock > waiters)
110		    {
111		      s->leftToUnblock = waiters;
112		    }
113		}
114#else
115	      if (ReleaseSemaphore (s->sem,  (waiters<=count)?waiters:count, 0))
116		{
117		  /* No action */
118		}
119#endif
120	      else
121		{
122		  s->value -= count;
123		  result = EINVAL;
124		}
125	    }
126	}
127      else
128	{
129	  result = ERANGE;
130	}
131      (void) pthread_mutex_unlock (&s->lock);
132    }
133
134  if (result != 0)
135    {
136      errno = result;
137      return -1;
138    }
139
140  return 0;
141
142}				/* sem_post_multiple */
143