Esempio n. 1
0
int
sem_trywait (sem_t * sem)
/*
 * ------------------------------------------------------
 * DOCPUBLIC
 *      This function tries to wait on a semaphore.
 *
 * PARAMETERS
 *      sem
 *              pointer to an instance of sem_t
 *
 * DESCRIPTION
 *      This function tries to wait on a semaphore. If the
 *      semaphore value is greater than zero, it decreases
 *      its value by one. If the semaphore value is zero, then
 *      this function returns immediately with the error EAGAIN
 *
 * RESULTS
 *              0               successfully decreased semaphore,
 *              -1              failed, error in errno
 * ERRNO
 *              EAGAIN          the semaphore was already locked,
 *              EINVAL          'sem' is not a valid semaphore,
 *              ENOTSUP         sem_trywait is not supported,
 *              EINTR           the function was interrupted by a signal,
 *              EDEADLK         a deadlock condition was detected.
 *
 * ------------------------------------------------------
 */
{
  int result = 0;
  sem_t s = *sem;
  ptw32_mcs_local_node_t node;

  ptw32_mcs_lock_acquire(&s->lock, &node);

  if (s->value > 0)
    {
      s->value--;
    }
  else
    {
      result = EAGAIN;
    }

  ptw32_mcs_lock_release(&node);

  if (result != 0)
    {
      PTW32_SET_ERRNO(result);
      return -1;
    }

  return 0;

}				/* sem_trywait */
int
sched_setscheduler (pid_t pid, int policy)
{
  /*
   * Win32 only has one policy which we call SCHED_OTHER.
   * However, we try to provide other valid side-effects
   * such as EPERM and ESRCH errors. Choosing to check
   * for a valid policy last allows us to get the most value out
   * of this function.
   */
  if (0 != pid)
    {
      int selfPid = (int) GetCurrentProcessId ();

      if (pid != selfPid)
	{
	  HANDLE h =
	    OpenProcess (PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) pid);

	  if (NULL == h)
	    {
	      PTW32_SET_ERRNO((GetLastError () == (0xFF & ERROR_ACCESS_DENIED)) ? EPERM : ESRCH);
	      return -1;
	    }
	  else
	    CloseHandle(h);
	}
    }

  if (SCHED_OTHER != policy)
    {
      PTW32_SET_ERRNO(ENOSYS);
      return -1;
    }

  /*
   * Don't set anything because there is nothing to set.
   * Just return the current (the only possible) value.
   */
  return SCHED_OTHER;
}
int
sched_setaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *set)
     /*
      * ------------------------------------------------------
      * DOCPUBLIC
      *      Sets the CPU affinity mask of the process whose ID is pid
      *	     to the value specified by mask.  If pid is zero, then the
      *	     calling process is used.  The argument cpusetsize is the
      *	     length (in bytes) of the data pointed to by mask.  Normally
      *	     this argument would be specified as sizeof(cpu_set_t).
      *
      *	     If the process specified by pid is not currently running on
      *	     one of the CPUs specified in mask, then that process is
      *	     migrated to one of the CPUs specified in mask.
      *
      * PARAMETERS
      *      pid
      *      			Process ID
      *
      *      cpusetsize
      *      			Currently ignored in pthreads4w.
      *      			Usually set to sizeof(cpu_set_t)
      *
      *      mask
      *      			Pointer to the CPU mask to set (cpu_set_t).
      *
      * DESCRIPTION
      *      Sets the CPU affinity mask of the process whose ID is pid
      *	     to the value specified by mask.  If pid is zero, then the
      *	     calling process is used.  The argument cpusetsize is the
      *	     length (in bytes) of the data pointed to by mask.  Normally
      *	     this argument would be specified as sizeof(cpu_set_t).
      *
      *	     If the process specified by pid is not currently running on
      *	     one of the CPUs specified in mask, then that process is
      *	     migrated to one of the CPUs specified in mask.
      *
      * RESULTS
      *              0               successfully created semaphore,
      *              EFAULT          'mask' is a NULL pointer.
      *              EINVAL          '*mask' contains no CPUs in the set
      *                              of available CPUs.
      *              EAGAIN          The system available CPUs could not
      *                              be obtained.
      *              EPERM           The process referred to by 'pid' is
      *                              not modifiable by us.
      *              ESRCH           The process referred to by 'pid' was
      *                              not found.
      *              ENOSYS			 Function not supported.
      *
      * ------------------------------------------------------
      */
{
#if ! defined(NEED_PROCESS_AFFINITY_MASK)

  DWORD_PTR vProcessMask;
  DWORD_PTR vSystemMask;
  HANDLE h;
  int targetPid = (int)(size_t) pid;
  int result = 0;

  if (NULL == set)
	{
	  result = EFAULT;
	}
  else
	{
	  if (0 == targetPid)
		{
		  targetPid = (int) GetCurrentProcessId ();
		}

	  h = OpenProcess (PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) targetPid);

	  if (NULL == h)
		{
		  result = (((0xFF & ERROR_ACCESS_DENIED) == GetLastError()) ? EPERM : ESRCH);
		}
	  else
		{
		  if (GetProcessAffinityMask (h, &vProcessMask, &vSystemMask))
			{
			  /*
			   * Result is the intersection of available CPUs and the mask.
			   */
			  DWORD_PTR newMask = vSystemMask & ((_sched_cpu_set_vector_*)set)->_cpuset;

			  if (newMask)
				{
				  if (SetProcessAffinityMask(h, newMask) == 0)
				    {
					  switch (GetLastError())
					    {
					  	  case (0xFF & ERROR_ACCESS_DENIED):
					  		  result = EPERM;
					  		  break;
					  	  case (0xFF & ERROR_INVALID_PARAMETER):
					  		  result = EINVAL;
					  		  break;
					  	  default:
					  		  result = EAGAIN;
					  		  break;
					    }
				    }
				}
			  else
				{
				  /*
				   * Mask does not contain any CPUs currently available on the system.
				   */
				  result = EINVAL;
				}
			}
		  else
			{
			  result = EAGAIN;
			}
		}
	  CloseHandle(h);
	}

  if (result != 0)
    {
	  PTW32_SET_ERRNO(result);
	  return -1;
    }
  else
    {
	  return 0;
    }

#else

  PTW32_SET_ERRNO(ENOSYS);
  return -1;

#endif
}
int
sched_getaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *set)
     /*
      * ------------------------------------------------------
      * DOCPUBLIC
      *      Gets the CPU affinity mask of the process whose ID is pid
      *	     to the value specified by mask.  If pid is zero, then the
      *	     calling process is used.  The argument cpusetsize is the
      *	     length (in bytes) of the data pointed to by mask.  Normally
      *	     this argument would be specified as sizeof(cpu_set_t).
      *
      * PARAMETERS
      *      pid
      *      			Process ID
      *
      *      cpusetsize
      *      			Currently ignored in pthreads4w.
      *      			Usually set to sizeof(cpu_set_t)
      *
      *      mask
      *      			Pointer to the CPU mask to set (cpu_set_t).
      *
      * DESCRIPTION
      *      Sets the CPU affinity mask of the process whose ID is pid
      *	     to the value specified by mask.  If pid is zero, then the
      *	     calling process is used.  The argument cpusetsize is the
      *	     length (in bytes) of the data pointed to by mask.  Normally
      *	     this argument would be specified as sizeof(cpu_set_t).
      *
      * RESULTS
      *              0               successfully created semaphore,
      *              EFAULT          'mask' is a NULL pointer.
      *              EAGAIN          The system available CPUs could not
      *                              be obtained.
      *              EPERM           The process referred to by 'pid' is
      *                              not modifiable by us.
      *              ESRCH           The process referred to by 'pid' was
      *                              not found.
      *
      * ------------------------------------------------------
      */
{
  DWORD_PTR vProcessMask;
  DWORD_PTR vSystemMask;
  HANDLE h;
  int targetPid = (int)(size_t) pid;
  int result = 0;

  if (NULL == set)
    {
	  result = EFAULT;
    }
  else
    {

#if ! defined(NEED_PROCESS_AFFINITY_MASK)

	  if (0 == targetPid)
	    {
		  targetPid = (int) GetCurrentProcessId ();
	    }

	  h = OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) targetPid);

	  if (NULL == h)
	    {
		  result = (((0xFF & ERROR_ACCESS_DENIED) == GetLastError()) ? EPERM : ESRCH);
	    }
	  else
	    {
		  if (GetProcessAffinityMask (h, &vProcessMask, &vSystemMask))
		    {
			  ((_sched_cpu_set_vector_*)set)->_cpuset = vProcessMask;
		    }
		  else
		    {
			  result = EAGAIN;
		    }
	    }
	  CloseHandle(h);

#else
	  ((_sched_cpu_set_vector_*)set)->_cpuset = (size_t)0x1;
#endif

    }

  if (result != 0)
    {
	  PTW32_SET_ERRNO(result);
	  return -1;
    }
  else
    {
	  return 0;
    }
}
Esempio n. 5
0
int
sem_timedwait (sem_t * sem, const struct timespec *abstime)
/*
 * ------------------------------------------------------
 * DOCPUBLIC
 *      This function waits on a semaphore possibly until
 *      'abstime' time.
 *
 * PARAMETERS
 *      sem
 *              pointer to an instance of sem_t
 *
 *      abstime
 *              pointer to an instance of struct timespec
 *
 * DESCRIPTION
 *      This function waits on a semaphore. If the
 *      semaphore value is greater than zero, it decreases
 *      its value by one. If the semaphore value is zero, then
 *      the calling thread (or process) is blocked until it can
 *      successfully decrease the value or until interrupted by
 *      a signal.
 *
 *      If 'abstime' is a NULL pointer then this function will
 *      block until it can successfully decrease the value or
 *      until interrupted by a signal.
 *
 * RESULTS
 *              0               successfully decreased semaphore,
 *              -1              failed, error in errno
 * ERRNO
 *              EINVAL          'sem' is not a valid semaphore,
 *              ENOSYS          semaphores are not supported,
 *              EINTR           the function was interrupted by a signal,
 *              EDEADLK         a deadlock condition was detected.
 *              ETIMEDOUT       abstime elapsed before success.
 *
 * ------------------------------------------------------
 */
{
  ptw32_mcs_local_node_t node;
  DWORD milliseconds;
  int v;
  int result = 0;
  sem_t s = *sem;

  pthread_testcancel();

  if (abstime == NULL)
    {
      milliseconds = INFINITE;
    }
  else
    {
      /*
       * Calculate timeout as milliseconds from current system time.
       */
      milliseconds = ptw32_relmillisecs (abstime);
    }

  ptw32_mcs_lock_acquire(&s->lock, &node);
  v = --s->value;
  ptw32_mcs_lock_release(&node);

  if (v < 0)
    {
#if defined(NEED_SEM)
      int timedout;
#endif
      sem_timedwait_cleanup_args_t cleanup_args;

      cleanup_args.sem = s;
      cleanup_args.resultPtr = &result;

#if defined(PTW32_CONFIG_MSVC7)
#pragma inline_depth(0)
#endif
      /* Must wait */
      pthread_cleanup_push(ptw32_sem_timedwait_cleanup, (void *) &cleanup_args);
#if defined(NEED_SEM)
      timedout =
#endif
          result = pthreadCancelableTimedWait (s->sem, milliseconds);
      pthread_cleanup_pop(result);
#if defined(PTW32_CONFIG_MSVC7)
#pragma inline_depth()
#endif

#if defined(NEED_SEM)

      if (!timedout)
        {
          ptw32_mcs_lock_acquire(&s->lock, &node);
          if (s->leftToUnblock > 0)
            {
              --s->leftToUnblock;
              SetEvent(s->sem);
            }
          ptw32_mcs_lock_release(&node);
        }

#endif /* NEED_SEM */

    }

  if (result != 0)
    {

      PTW32_SET_ERRNO(result);
      return -1;

    }

  return 0;

}				/* sem_timedwait */
Esempio n. 6
0
int
sem_init (sem_t * sem, int pshared, unsigned int value)
     /*
      * ------------------------------------------------------
      * DOCPUBLIC
      *      This function initializes a semaphore. The
      *      initial value of the semaphore is 'value'
      *
      * PARAMETERS
      *      sem
      *              pointer to an instance of sem_t
      *
      *      pshared
      *              if zero, this semaphore may only be shared between
      *              threads in the same process.
      *              if nonzero, the semaphore can be shared between
      *              processes
      *
      *      value
      *              initial value of the semaphore counter
      *
      * DESCRIPTION
      *      This function initializes a semaphore. The
      *      initial value of the semaphore is set to 'value'.
      *
      * RESULTS
      *              0               successfully created semaphore,
      *              -1              failed, error in errno
      * ERRNO
      *              EINVAL          'sem' is not a valid semaphore, or
      *                              'value' >= SEM_VALUE_MAX
      *              ENOMEM          out of memory,
      *              ENOSPC          a required resource has been exhausted,
      *              ENOSYS          semaphores are not supported,
      *              EPERM           the process lacks appropriate privilege
      *
      * ------------------------------------------------------
      */
{
  int result = 0;
  sem_t s = NULL;

  if (pshared != 0)
    {
      /*
       * Creating a semaphore that can be shared between
       * processes
       */
      result = EPERM;
    }
  else if (value > (unsigned int)SEM_VALUE_MAX)
    {
      result = EINVAL;
    }
  else
    {
      s = (sem_t) calloc (1, sizeof (*s));

      if (NULL == s)
	{
	  result = ENOMEM;
	}
      else
	{

	  s->value = value;
	  if (pthread_mutex_init(&s->lock, NULL) == 0)
	    {

#if defined(NEED_SEM)

	  s->sem = CreateEvent (NULL,
				PTW32_FALSE,	/* auto (not manual) reset */
				PTW32_FALSE,	/* initial state is unset */
				NULL);

	  if (0 == s->sem)
	    {
	      (void) pthread_mutex_destroy(&s->lock);
	      result = ENOSPC;
	    }
	  else
	    {
	      s->leftToUnblock = 0;
	    }

#else /* NEED_SEM */

	      if ((s->sem = CreateSemaphore (NULL,	/* Always NULL */
					     (long) 0,	/* Force threads to wait */
					     (long) SEM_VALUE_MAX,	/* Maximum value */
					     NULL)) == 0)	/* Name */
		{
		  (void) pthread_mutex_destroy(&s->lock);
		  result = ENOSPC;
		}

#endif /* NEED_SEM */

	    }
	  else
	    {
	      result = ENOSPC;
	    }

	  if (result != 0)
	    {
	      free(s);
	    }
	}
    }

  if (result != 0)
    {
      PTW32_SET_ERRNO(result);
      return -1;
    }

  *sem = s;

  return 0;

}				/* sem_init */
Esempio n. 7
0
int
sem_open (const char *name, int oflag, mode_t mode, unsigned int value)
{
  PTW32_SET_ERRNO(ENOSYS);
  return -1;
}				/* sem_open */
Esempio n. 8
0
int
sem_destroy (sem_t * sem)
     /*
      * ------------------------------------------------------
      * DOCPUBLIC
      *      This function destroys an unnamed semaphore.
      *
      * PARAMETERS
      *      sem
      *              pointer to an instance of sem_t
      *
      * DESCRIPTION
      *      This function destroys an unnamed semaphore.
      *
      * RESULTS
      *              0               successfully destroyed semaphore,
      *              -1              failed, error in errno
      * ERRNO
      *              EINVAL          'sem' is not a valid semaphore,
      *              ENOSYS          semaphores are not supported,
      *              EBUSY           threads (or processes) are currently
      *                                      blocked on 'sem'
      *
      * ------------------------------------------------------
      */
{
  int result = 0;
  sem_t s = NULL;

  if (sem == NULL || *sem == NULL)
    {
      result = EINVAL;
    }
  else
    {
      s = *sem;

      if ((result = pthread_mutex_lock (&s->lock)) == 0)
        {
          if (s->value < 0)
            {
              (void) pthread_mutex_unlock (&s->lock);
              result = EBUSY;
            }
          else
            {
              /* There are no threads currently blocked on this semaphore. */

              if (!CloseHandle (s->sem))
	        {
                  (void) pthread_mutex_unlock (&s->lock);
	          result = EINVAL;
	        }
	      else
	        {
                  /*
                   * Invalidate the semaphore handle when we have the lock.
                   * Other sema operations should test this after acquiring the lock
                   * to check that the sema is still valid, i.e. before performing any
                   * operations. This may only be necessary before the sema op routine
                   * returns so that the routine can return EINVAL - e.g. if setting
                   * s->value to SEM_VALUE_MAX below does force a fall-through.
                   */
                  *sem = NULL;

                  /* Prevent anyone else actually waiting on or posting this sema.
                   */
                  s->value = SEM_VALUE_MAX;

                  (void) pthread_mutex_unlock (&s->lock);

                  do
                    {
                      /* Give other threads a chance to run and exit any sema op
                       * routines. Due to the SEM_VALUE_MAX value, if sem_post or
                       * sem_wait were blocked by us they should fall through.
                       */
                      Sleep(0);
                    }
                  while (pthread_mutex_destroy (&s->lock) == EBUSY);
                }
            }
        }
    }

  if (result != 0)
    {
      PTW32_SET_ERRNO(result);
      return -1;
    }

  free (s);

  return 0;

}				/* sem_destroy */
Esempio n. 9
0
int
sem_destroy (sem_t * sem)
/*
 * ------------------------------------------------------
 * DOCPUBLIC
 *      This function destroys an unnamed semaphore.
 *
 * PARAMETERS
 *      sem
 *              pointer to an instance of sem_t
 *
 * DESCRIPTION
 *      This function destroys an unnamed semaphore.
 *
 * RESULTS
 *              0               successfully destroyed semaphore,
 *              -1              failed, error in errno
 * ERRNO
 *              EINVAL          'sem' is not a valid semaphore,
 *              ENOSYS          semaphores are not supported,
 *              EBUSY           threads (or processes) are currently
 *                                      blocked on 'sem'
 *
 * ------------------------------------------------------
 */
{
  int result = 0;
  sem_t s = NULL;

  if (sem == NULL || *sem == NULL)
    {
      result = EINVAL;
    }
  else
    {
      ptw32_mcs_local_node_t node;
      s = *sem;

      if ((result = ptw32_mcs_lock_try_acquire(&s->lock, &node)) == 0)
        {
          if (s->value < 0)
            {
              result = EBUSY;
            }
          else
            {
              /*
               * There are no threads currently blocked on this semaphore
               * however there could be threads about to wait behind us.
               * It is up to the application to ensure this is not the case.
               */
              if (!CloseHandle (s->sem))
                {
                  result = EINVAL;
                }
            }
          ptw32_mcs_lock_release(&node);
        }
    }

  if (result != 0)
    {
      PTW32_SET_ERRNO(result);
      return -1;
    }

  free (s);

  return 0;

}				/* sem_destroy */
Esempio n. 10
0
int
ptw32_semwait (sem_t * sem)
     /*
      * ------------------------------------------------------
      * DESCRIPTION
      *      This function waits on a POSIX semaphore. If the
      *      semaphore value is greater than zero, it decreases
      *      its value by one. If the semaphore value is zero, then
      *      the calling thread (or process) is blocked until it can
      *      successfully decrease the value.
      *
      *      Unlike sem_wait(), this routine is non-cancelable.
      *
      * RESULTS
      *              0               successfully decreased semaphore,
      *              -1              failed, error in errno.
      * ERRNO
      *              EINVAL          'sem' is not a valid semaphore,
      *              ENOSYS          semaphores are not supported,
      *              EINTR           the function was interrupted by a signal,
      *              EDEADLK         a deadlock condition was detected.
      *
      * ------------------------------------------------------
      */
{
  int result = 0;
  sem_t s = *sem;

  if (s == NULL)
    {
      result = EINVAL;
    }
  else
    {
      if ((result = pthread_mutex_lock (&s->lock)) == 0)
        {
          int v;

	  /* See sem_destroy.c
	   */
	  if (*sem == NULL)
	    {
	      (void) pthread_mutex_unlock (&s->lock);
	      PTW32_SET_ERRNO(EINVAL);
	      return -1;
	    }

          v = --s->value;
          (void) pthread_mutex_unlock (&s->lock);

          if (v < 0)
            {
              /* Must wait */
              if (WaitForSingleObject (s->sem, INFINITE) == WAIT_OBJECT_0)
		{
#if defined(NEED_SEM)
		  if (pthread_mutex_lock (&s->lock) == 0)
		    {
        	      if (*sem == NULL)
        	        {
        	          (void) pthread_mutex_unlock (&s->lock);
        	          PTW32_SET_ERRNO(EINVAL);
        	          return -1;
        	        }

		      if (s->leftToUnblock > 0)
			{
			  --s->leftToUnblock;
			  SetEvent(s->sem);
			}
		      (void) pthread_mutex_unlock (&s->lock);
		    }
#endif
		  return 0;
		}
            }
          else
	    {
	      return 0;
	    }
        }
    }

  if (result != 0)
    {
      PTW32_SET_ERRNO(result);
      return -1;
    }

  return 0;

}				/* ptw32_semwait */