OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [runtime/] [thread-sema.c] - Rev 747

Compare with Previous | Blame | View Log

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
 
#include "config.h"
#include "runtime.h"
 
#include <errno.h>
#include <stdlib.h>
#include <time.h>
#include <semaphore.h>
 
/* If we don't have sem_timedwait, use pthread_cond_timedwait instead.
   We don't always use condition variables because on some systems
   pthread_mutex_lock and pthread_mutex_unlock must be called by the
   same thread.  That is never true of semaphores.  */
 
struct go_sem
{
  sem_t sem;
 
#ifndef HAVE_SEM_TIMEDWAIT
  int timedwait;
  pthread_mutex_t mutex;
  pthread_cond_t cond;
#endif
};
 
/* Create a semaphore.  */
 
uintptr
runtime_semacreate(void)
{
  struct go_sem *p;
 
  /* Call malloc rather than runtime_malloc.  This will allocate space
     on the C heap.  We can't call runtime_malloc here because it
     could cause a deadlock.  */
  p = malloc (sizeof (struct go_sem));
  if (sem_init (&p->sem, 0, 0) != 0)
    runtime_throw ("sem_init");
 
#ifndef HAVE_SEM_TIMEDWAIT
  if (pthread_mutex_init (&p->mutex, NULL) != 0)
    runtime_throw ("pthread_mutex_init");
  if (pthread_cond_init (&p->cond, NULL) != 0)
    runtime_throw ("pthread_cond_init");
#endif
 
  return (uintptr) p;
}
 
/* Acquire m->waitsema.  */
 
int32
runtime_semasleep (int64 ns)
{
  M *m;
  struct go_sem *sem;
  int r;
 
  m = runtime_m ();
  sem = (struct go_sem *) m->waitsema;
  if (ns >= 0)
    {
      int64 abs;
      struct timespec ts;
      int err;
 
      abs = ns + runtime_nanotime ();
      ts.tv_sec = abs / 1000000000LL;
      ts.tv_nsec = abs % 1000000000LL;
 
      err = 0;
 
#ifdef HAVE_SEM_TIMEDWAIT
      r = sem_timedwait (&sem->sem, &ts);
      if (r != 0)
	err = errno;
#else
      if (pthread_mutex_lock (&sem->mutex) != 0)
	runtime_throw ("pthread_mutex_lock");
 
      while ((r = sem_trywait (&sem->sem)) != 0)
	{
	  r = pthread_cond_timedwait (&sem->cond, &sem->mutex, &ts);
	  if (r != 0)
	    {
	      err = r;
	      break;
	    }
	}
 
      if (pthread_mutex_unlock (&sem->mutex) != 0)
	runtime_throw ("pthread_mutex_unlock");
#endif
 
      if (err != 0)
	{
	  if (err == ETIMEDOUT || err == EAGAIN || err == EINTR)
	    return -1;
	  runtime_throw ("sema_timedwait");
	}
      return 0;
    }
 
  while (sem_wait (&sem->sem) != 0)
    {
      if (errno == EINTR)
	continue;
      runtime_throw ("sem_wait");
    }
 
  return 0;
}
 
/* Wake up mp->waitsema.  */
 
void
runtime_semawakeup (M *mp)
{
  struct go_sem *sem;
 
  sem = (struct go_sem *) mp->waitsema;
  if (sem_post (&sem->sem) != 0)
    runtime_throw ("sem_post");
 
#ifndef HAVE_SEM_TIMEDWAIT
  if (pthread_mutex_lock (&sem->mutex) != 0)
    runtime_throw ("pthread_mutex_lock");
  if (pthread_cond_broadcast (&sem->cond) != 0)
    runtime_throw ("pthread_cond_broadcast");
  if (pthread_mutex_unlock (&sem->mutex) != 0)
    runtime_throw ("pthread_mutex_unlock");
#endif
}
 
void
runtime_osinit (void)
{
}
 
void
runtime_goenvs (void)
{
  runtime_goenvs_unix ();
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.