CS350 COS
COS
Loading...
Searching...
No Matches
pthread.c
Go to the documentation of this file.
1
2#include <stdbool.h>
3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7
8#include <unistd.h>
9#include <errno.h>
10#include <pthread.h>
11
12#include <core/mutex.h>
13
14#include <syscall.h>
15#include <sys/syscall.h>
16
19};
20
21struct pthread {
23 int error; // errno
24 TAILQ_ENTRY(pthread) threadTable;
25
26 // Initialization
27 void *(*entry)(void *);
28 void *arg;
29
30 // Termination
31 void *result;
32
33 // Condition Variables
34 TAILQ_ENTRY(pthread) cvTable;
35};
36
37typedef TAILQ_HEAD(pthreadList, pthread) pthreadList;
38
39#define THREAD_HASH_SLOTS 32
40
41static CoreMutex __threadTableLock;
42static pthreadList __threads[THREAD_HASH_SLOTS];
43
44int *
45__error(void)
46{
47 struct pthread *pth = pthread_self();
48
49 return &(pth->error);
50}
51
52void
54{
55 int i;
56 struct pthread *thr = (struct pthread *)malloc(sizeof(*thr));
57
58 for (i = 0; i < THREAD_HASH_SLOTS; i++) {
59 TAILQ_INIT(&__threads[i]);
60 }
61
62 if (thr == NULL) {
63 abort();
64 }
65
66 thr->tid = OSGetTID();
67 thr->error = 0;
68 thr->entry = NULL;
69 thr->arg = 0;
70
71 CoreMutex_Init(&__threadTableLock);
72
73 CoreMutex_Lock(&__threadTableLock);
74 TAILQ_INSERT_HEAD(&__threads[thr->tid % THREAD_HASH_SLOTS], thr, threadTable);
75 CoreMutex_Unlock(&__threadTableLock);
76}
77
80{
81 int tid = OSGetTID();
82 struct pthread *thr;
83
84 CoreMutex_Lock(&__threadTableLock);
85 TAILQ_FOREACH(thr, &__threads[tid % THREAD_HASH_SLOTS], threadTable) {
86 if (thr->tid == tid) {
87 CoreMutex_Unlock(&__threadTableLock);
88 return thr;
89 }
90 }
91 CoreMutex_Unlock(&__threadTableLock);
92
93 printf("pthread_self failed to find current thread!\n");
94 abort();
95}
96
97void
99{
100 struct pthread *thr = (struct pthread *)arg;
101
102 thr->result = (thr->entry)(thr->arg);
103
104 OSThreadExit(0);
105}
106
107int
109 void *(*start_routine)(void *), void *arg)
110{
111 uint64_t status;
112 struct pthread *thr;
113
114 thr = malloc(sizeof(*thr));
115 if (!thr) {
116 return EAGAIN;
117 }
118
119 memset(thr, 0, sizeof(*thr));
120
121 thr->entry = start_routine;
122 thr->arg = arg;
123
125 if (SYSCALL_ERRCODE(status) != 0) {
126 free(thr);
127 return SYSCALL_ERRCODE(status);
128 }
129
130 thr->tid = SYSCALL_VALUE(status);
131
132 CoreMutex_Lock(&__threadTableLock);
133 TAILQ_INSERT_HEAD(&__threads[thr->tid % THREAD_HASH_SLOTS], thr, threadTable);
134 CoreMutex_Unlock(&__threadTableLock);
135
136 *thread = thr;
137
138 return 0;
139}
140
141void
142pthread_exit(void *value_ptr)
143{
144 struct pthread *thr = pthread_self();
145
146 thr->result = value_ptr;
147
148 OSThreadExit(0);
149}
150
151int
152pthread_join(pthread_t thread, void **value_ptr)
153{
154 struct pthread *thr = thread;
155 uint64_t status = OSThreadWait(0);//thr->tid);
156 if (SYSCALL_ERRCODE(status) != 0) {
157 return status;
158 }
159
160 *value_ptr = (void *)thr->result;
161
162 CoreMutex_Lock(&__threadTableLock);
163 TAILQ_REMOVE(&__threads[thr->tid % THREAD_HASH_SLOTS], thr, threadTable);
164 CoreMutex_Unlock(&__threadTableLock);
165
166 // Cleanup
167 free(thr);
168
169 return 0;
170}
171
172void
174{
175 OSThreadSleep(0);
176}
177
178/*
179 * Barriers
180 */
181
182int
184 const pthread_barrierattr_t *attr,
185 unsigned count)
186{
187 return EINVAL;
188}
189
190int
192{
193 return EINVAL;
194}
195
196int
198{
199 return EINVAL;
200}
201
202/*
203 * Mutex
204 */
205
208};
209
212};
213
214int
216{
217 struct pthread_mutex *mtx = (struct pthread_mutex *)malloc(sizeof(*mtx));
218
219 if (mtx == NULL) {
220 return ENOMEM;
221 }
222
223 mtx->lock = 0;
224 *mutex = mtx;
225
226 return 0;
227}
228
229int
231{
232 struct pthread_mutex *mtx = *mutex;
233
234 if (mtx == NULL) {
235 return EINVAL;
236 } else if (mtx->lock == 1) {
237 return EBUSY;
238 } else {
239 *mutex = NULL;
240 free(mtx);
241 return 0;
242 }
243}
244
245int
247{
248 struct pthread_mutex *mtx;
249
250 if (*mutex == NULL) {
251 int status = pthread_mutex_init(mutex, NULL);
252 if (status != 0)
253 return status;
254 }
255
256 mtx = *mutex;
257
258 // XXX: Should have the kernel wait kernel instead of yielding
259 while (__sync_lock_test_and_set(&mtx->lock, 1) == 1) {
260 OSThreadSleep(0);
261 }
262
263 return 0;
264}
265
266int
268{
269 struct pthread_mutex *mtx;
270
271 if (*mutex == NULL) {
272 int status = pthread_mutex_init(mutex, NULL);
273 if (status != 0)
274 return status;
275 }
276
277 mtx = *mutex;
278
279 if (__sync_lock_test_and_set(&mtx->lock, 1) == 1) {
280 return EBUSY;
281 } else {
282 // Lock acquired
283 return 0;
284 }
285}
286
287int
289{
290 struct pthread_mutex *mtx;
291
292 if (*mutex == NULL) {
293 int status = pthread_mutex_init(mutex, NULL);
294 if (status != 0)
295 return status;
296 }
297
298 mtx = *mutex;
299
300 __sync_lock_release(&mtx->lock);
301 // XXX: Wakeup a sleeping thread
302
303 return 0;
304}
305
306
307/*
308 * Reader/Writer Lock
309 */
310
311/*
312 * Condition Variables
313 */
314
317};
318
323};
324
325int
327{
328 struct pthread_cond *cnd = (struct pthread_cond *)malloc(sizeof(*cnd));
329
330 if (cnd == NULL) {
331 return ENOMEM;
332 }
333
334 CoreMutex_Init(&cnd->mtx);
335 cnd->enter = 0;
336 cnd->exit = 0;
337
338 *cond = cnd;
339
340 return 0;
341}
342
343int
345{
346 struct pthread_cond *cnd = *cond;
347
348 *cond = NULL;
349 free(cnd);
350
351 return 0;
352}
353
354int
356{
357 int status;
358 struct pthread_cond *cnd;
359 uint64_t level;
360
361 if (*cond == NULL) {
362 status = pthread_cond_init(cond, NULL);
363 if (status != 0)
364 return status;
365 }
366 cnd = *cond;
367
368 if (mutex) {
369 status = pthread_mutex_unlock(mutex);
370 if (status != 0)
371 return status;
372 }
373
374 CoreMutex_Lock(&cnd->mtx);
375 level = cnd->enter;
376 cnd->enter++;
377 CoreMutex_Unlock(&cnd->mtx);
378
379 while (level >= cnd->exit) {
380 OSThreadSleep(0);
381 }
382
383 if (mutex) {
384 status = pthread_mutex_lock(mutex);
385 if (status != 0)
386 return status;
387 }
388
389 return 0;
390}
391
392int
394 const struct timespec *abstime)
395{
396 int status = 0;
397 int rstatus = 0;
398 struct pthread_cond *cnd;
399 uint64_t level;
400 uint64_t endtime = abstime->tv_sec * 1000000000 + abstime->tv_nsec;
401
402 if (*cond == NULL) {
403 status = pthread_cond_init(cond, NULL);
404 if (status != 0)
405 return status;
406 }
407 cnd = *cond;
408
409 if (mutex) {
410 status = pthread_mutex_unlock(mutex);
411 if (status != 0)
412 return status;
413 }
414
415 CoreMutex_Lock(&cnd->mtx);
416 level = cnd->enter;
417 cnd->enter++;
418 CoreMutex_Unlock(&cnd->mtx);
419
420 while (level >= cnd->exit) {
421 OSThreadSleep(0);
422
423 if (endtime < OSTime()) {
424 rstatus = ETIMEDOUT;
425 break;
426 }
427 }
428
429 if (mutex) {
430 status = pthread_mutex_lock(mutex);
431 if (status != 0)
432 return status;
433 }
434
435 return rstatus;
436}
437
438
439int
441{
442 struct pthread_cond *cnd;
443
444 if (*cond == NULL) {
445 int status = pthread_cond_init(cond, NULL);
446 if (status != 0)
447 return status;
448 }
449 cnd = *cond;
450
451 CoreMutex_Lock(&cnd->mtx);
452 cnd->exit++;
453 CoreMutex_Unlock(&cnd->mtx);
454
455 return 0;
456}
457
458int
460{
461 struct pthread_cond *cnd;
462
463 if (*cond == NULL) {
464 int status = pthread_cond_init(cond, NULL);
465 if (status != 0)
466 return status;
467 }
468 cnd = *cond;
469
470 CoreMutex_Lock(&cnd->mtx);
471 cnd->exit = cnd->enter;
472 CoreMutex_Unlock(&cnd->mtx);
473
474 return 0;
475}
476
#define EINVAL
Definition: errno.h:12
#define ETIMEDOUT
Definition: errno.h:25
#define ENOMEM
Definition: errno.h:14
#define EBUSY
Definition: errno.h:20
int * __error()
#define EAGAIN
Definition: errno.h:19
void CoreMutex_Lock(CoreMutex *mtx)
Definition: mutex.c:16
void CoreMutex_Unlock(CoreMutex *mtx)
Definition: mutex.c:34
void CoreMutex_Init(CoreMutex *mtx)
Definition: mutex.c:9
Definition: mutex.h:5
int OSThreadSleep(uint64_t time)
Definition: syscall.c:125
uint64_t OSTime()
Definition: syscall.c:11
int OSThreadExit(uint64_t status)
Definition: syscall.c:119
int OSGetTID()
Definition: syscall.c:113
int OSThreadWait(uint64_t tid)
Definition: syscall.c:131
int OSThreadCreate(uint64_t rip, uint64_t arg)
Definition: syscall.c:107
void pthread_exit(void *value_ptr)
Definition: pthread.c:142
int pthread_mutex_lock(pthread_mutex_t *mutex)
Definition: pthread.c:246
int pthread_cond_signal(pthread_cond_t *cond)
Definition: pthread.c:440
int pthread_mutex_trylock(pthread_mutex_t *mutex)
Definition: pthread.c:267
int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: pthread.c:230
uint64_t _unused
Definition: pthread.c:207
#define THREAD_HASH_SLOTS
pthread_t pthread_self(void)
Definition: pthread.c:79
CoreMutex mtx
Definition: pthread.c:320
uint64_t _unused
Definition: pthread.c:18
uint64_t tid
Definition: pthread.c:22
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: pthread.c:215
void pthread_yield(void)
Definition: pthread.c:173
int pthread_barrier_wait(pthread_barrier_t *barrier)
Definition: pthread.c:197
uint64_t exit
Definition: pthread.c:322
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: pthread.c:355
int pthread_mutex_unlock(pthread_mutex_t *mutex)
Definition: pthread.c:288
int pthread_cond_destroy(pthread_cond_t *cond)
Definition: pthread.c:344
int pthread_join(pthread_t thread, void **value_ptr)
Definition: pthread.c:152
void __pthread_init(void)
Definition: pthread.c:53
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime)
Definition: pthread.c:393
uint64_t lock
Definition: pthread.c:211
uint64_t _unused
Definition: pthread.c:316
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: pthread.c:326
int error
Definition: pthread.c:23
int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned count)
Definition: pthread.c:183
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition: pthread.c:108
void pthreadCreateHelper(void *arg)
Definition: pthread.c:98
int pthread_barrier_destroy(pthread_barrier_t *barrier)
Definition: pthread.c:191
uint64_t enter
Definition: pthread.c:321
int pthread_cond_broadcast(pthread_cond_t *cond)
Definition: pthread.c:459
struct pthread_barrier * pthread_barrier_t
Definition: pthread.h:12
struct pthread_barrierattr * pthread_barrierattr_t
Definition: pthread.h:13
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:557
#define TAILQ_INIT(head)
Definition: queue.h:597
#define TAILQ_HEAD(name, type)
Definition: queue.h:491
#define TAILQ_REMOVE(head, elm, field)
Definition: queue.h:659
#define TAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:628
#define TAILQ_ENTRY(type)
Definition: queue.h:501
#define NULL
Definition: stddef.h:6
int printf(const char *fmt,...)
Definition: printf.c:212
void free(void *buf)
Definition: malloc.c:169
_Noreturn void abort(void)
Definition: abort.c:9
void * malloc(size_t sz)
Definition: malloc.c:160
void * memset(void *dst, int c, size_t len)
Definition: string.c:164
#define SYSCALL_ERRCODE(_result)
Definition: syscall.h:56
#define SYSCALL_VALUE(_result)
Definition: syscall.h:57
long tv_nsec
Definition: timespec.h:9
time_t tv_sec
Definition: timespec.h:8
uint64_t uintptr_t
Definition: types.h:16
unsigned long uint64_t
Definition: types.h:13