Add semaphore stuff for pthreads
authorKevin Klues <klueska@cs.berkeley.edu>
Wed, 5 Dec 2012 04:21:27 +0000 (20:21 -0800)
committerKevin Klues <klueska@cs.berkeley.edu>
Wed, 5 Dec 2012 04:21:27 +0000 (20:21 -0800)
user/pthread/semaphore.c [new file with mode: 0644]
user/pthread/semaphore.h

diff --git a/user/pthread/semaphore.c b/user/pthread/semaphore.c
new file mode 100644 (file)
index 0000000..57a820e
--- /dev/null
@@ -0,0 +1,99 @@
+#include <uthread.h>
+#include <semaphore.h>
+#include <mcs.h>
+#include <stdio.h>
+
+int sem_init (sem_t *__sem, int __pshared, unsigned int __value)
+{
+       if(__pshared == TRUE) {
+               printf("__pshared functionality of sem_init is not yet implemented!");
+               return -1;
+       }
+       __sem->count = __value;
+       TAILQ_INIT(&__sem->queue);
+       mcs_pdr_init(&__sem->lock);
+       return 0;
+}
+
+int sem_destroy (sem_t *__sem)
+{
+       return 0;
+}
+
+sem_t *sem_open (__const char *__name, int __oflag, ...)
+{
+       printf("sem_open is not yet implemented!");
+       return NULL;
+}
+
+int sem_close (sem_t *__sem)
+{
+       printf("sem_close is not yet implemented!");
+       return -1;
+}
+
+int sem_unlink (__const char *__name)
+{
+       printf("sem_unlink is not yet implemented!");
+       return -1;
+}
+
+static void __sem_block(struct uthread *uthread, void *arg) {
+       sem_t *__sem = (sem_t*)arg;
+    pthread_t pthread = (pthread_t)uthread;
+       TAILQ_INSERT_TAIL(&__sem->queue, pthread, next);
+       mcs_pdr_unlock(&__sem->lock);
+}
+
+int sem_wait (sem_t *__sem)
+{
+       mcs_pdr_lock(&__sem->lock);
+       if(__sem->count > 0) {
+               __sem->count--;
+               mcs_pdr_unlock(&__sem->lock);
+       }
+       else {
+               // We unlock in the body of __sem_block
+               uthread_yield(TRUE, __sem_block, __sem);
+       }
+       return 0;
+}
+
+int sem_trywait (sem_t *__sem)
+{
+       int ret = -1;
+       mcs_pdr_lock(&__sem->lock);
+       if(__sem->count > 0) {
+               __sem->count--;
+               ret = 0;
+       }
+       mcs_pdr_unlock(&__sem->lock);
+       return ret;
+}
+
+int sem_post (sem_t *__sem)
+{
+       int ret = -1;
+       mcs_pdr_lock(&__sem->lock);
+    pthread_t pthread = TAILQ_FIRST(&__sem->queue);
+       if(pthread != NULL) {
+               TAILQ_REMOVE(&__sem->queue, pthread, next);
+               __sem->count++;
+       }
+       mcs_pdr_unlock(&__sem->lock);
+
+       if(ret == 0) {
+               pthread->state = PTH_BLK_MUTEX;
+               uthread_runnable((struct uthread*)pthread);
+       }
+       return ret;
+}
+
+int sem_getvalue (sem_t *__restrict __sem, int *__restrict __sval)
+{
+       mcs_pdr_lock(&__sem->lock);
+       *__sval = __sem->count;
+       mcs_pdr_unlock(&__sem->lock);
+       return 0;
+}
+
index 1b5b49b..cbf8af0 100644 (file)
    02111-1307 USA.  */
 
 #ifndef _SEMAPHORE_H
-#define _SEMAPHORE_H   1
+#define _SEMAPHORE_H
 
-/* Get the definition for sem_t.  */
-#define __SIZEOF_SEM_T 16
+#include <sys/queue.h>
+#include <pthread.h>
+#include <mcs.h>
 
 /* Value returned if `sem_open' failed.  */
 #define SEM_FAILED      ((sem_t *) 0)
 
-typedef union
+typedef struct sem
 {
-  char __size[__SIZEOF_SEM_T];
-  long int __attribute__ ((aligned (__BIGGEST_ALIGNMENT__)));
+       unsigned int count;
+       struct pthread_queue queue;
+       struct mcs_pdr_lock lock;
 } sem_t;
 
 extern int sem_init (sem_t *__sem, int __pshared, unsigned int __value);