-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy paththread.h
152 lines (130 loc) · 6.22 KB
/
thread.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#ifndef _THREAD_H_
#define _THREAD_H_
typedef int Tid;
#define THREAD_MAX_THREADS 1024
#define THREAD_MIN_STACK 32768
/*
* Valid thread identifiers (Tid) range between 0 and THREAD_MAX_THREADS-1. The
* first thread to run must have a thread id of 0. Note that this thread is the
* main thread, i.e., it is created before the first call to
* thread_create. Negative Tid values are used for error codes or control codes.
*/
enum { THREAD_ANY = -1,
THREAD_SELF = -2,
THREAD_INVALID = -3,
THREAD_NONE = -4,
THREAD_NOMORE = -5,
THREAD_NOMEMORY = -6,
THREAD_FAILED = -7
};
static inline int
thread_ret_ok(Tid ret)
{
return (ret >= 0 ? 1 : 0);
}
/* perform any initialization needed by your threading system */
void thread_init(void);
/* return the thread identifier of the currently running thread */
Tid thread_id(void);
/* thread_create should create a thread that starts running the function
* fn(arg). Upon success, return the thread identifier. On failure, return the
* following:
*
* THREAD_NOMORE: no more threads can be created.
* THREAD_NOMEMORY: no more memory available to create a thread stack. */
Tid thread_create(void (*fn) (void *), void *arg);
/* thread_yield should suspend the calling thread and run the thread with
* identifier tid. The calling thread is put in the ready queue. tid can be
* identifier of any available thread or the following constants:
*
* THREAD_ANY: run any thread in the ready queue.
* THREAD_SELF: continue executing calling thread, for debugging purposes.
*
* Upon success, return the identifier of the thread that ran. The calling
* thread does not see this result until it runs later. Upon failure, the
* calling thread continues running, and returns the following:
*
* THREAD_INVALID: identifier tid does not correspond to a valid thread.
* THREAD_NONE: no more threads, other than the caller, are available to
* run. this can happen is response to a call with tid set to
* THREAD_ANY. */
Tid thread_yield(Tid tid);
/* thread_exit should ensure that the current thread does not run after this
* call, i.e., this function should never return. If there are other threads in
* the system, one of them should be run. If there are no other threads (this is
* the last thread invoking thread_exit), then the program should exit. In the
* future, a new thread should be able to reuse this thread's identifier. The
* function has no return values. */
void thread_exit(void);
/* Kill a thread whose identifier is tid. When a thread is killed, it should not
* run any further. The calling thread continues to execute and receives the
* result of the call. tid can be the identifier of any available thread.
*
* Upon success, return the identifier of the thread that was killed. Upon
* failure, return the following:
*
* THREAD_INVALID: identifier tid does not correspond to a valid thread (e.g.,
* any negative value of tid), or it is the current thread.
*/
Tid thread_kill(Tid tid);
/* create a queue of waiting threads. initially, the queue is empty. */
struct wait_queue *wait_queue_create(void);
/* destroy the wait queue. be sure to check that the queue is empty when it is
* being destroyed. */
void wait_queue_destroy(struct wait_queue *wq);
/* suspend calling thread and run some other thread. The calling thread is put
* in the wait queue. Upon success, return the identifier of the thread that
* ran. The calling thread does not see this result until it runs later. Upon
* failure, the calling thread continues running, and returns the following:
*
* THREAD_INVALID: queue is invalid, e.g., it is NULL.
* THREAD_NONE: no more threads, other than the caller, are available to
* run. */
Tid thread_sleep(struct wait_queue *queue);
/* wake up one or more threads that are suspended in the wait queue. These
* threads are put in the ready queue. The calling thread continues to execute
* and receives the result of the call. When "all" is 0, then one thread is
* woken up. When "all" is 1, all suspended threads are woken up. Wake up
* threads in FIFO order, i.e., first thread to sleep must be woken up
* first. The function returns the number of threads that were woken up. It can
* return zero if there were no suspended threads in the wait queue. */
int thread_wakeup(struct wait_queue *queue, int all);
/* suspend current thread until the thread whose identifier is tid exits. Upon
* sucess, return the identifier of the thread that exited. Upon
* failure, return the following:
*
* THREAD_INVALID: identifier tid does not correspond to a valid thread (e.g.,
* any negative value of tid), or it is the current thread.
*/
int thread_wait(Tid tid);
/* create a blocking lock. initially, the lock is available. associate a wait
* queue with the lock so that threads that need to acquire the lock can wait in
* this queue. */
struct lock *lock_create();
/* destroy the lock. be sure to check that the lock is available when it is
* being destroyed. */
void lock_destroy(struct lock *lock);
/* acquire the lock. threads should be suspended until they can acquire the
* lock. */
void lock_acquire(struct lock *lock);
/* release the lock. be sure to check that the lock had been acquired by the
* calling thread, before it is released. wakeup all threads that are waiting to
* acquire the lock. */
void lock_release(struct lock *lock);
/* create a condition variable. associate a wait queue with the condition
* variable so that threads issuing cv_wait can wait in this queue. */
struct cv *cv_create();
/* destroy the condition variable. */
void cv_destroy(struct cv *cv);
/* suspend the calling thread on the condition variable cv. be sure to check
* that the calling thread had acquired lock when this call is made. you will
* need to release the lock before waiting, and reacquire it before returning
* from wait. */
void cv_wait(struct cv *cv, struct lock *lock);
/* wake up one thread that is waiting on the condition variable cv. be sure to
* check that the calling thread had acquired lock when this call is made. */
void cv_signal(struct cv *cv, struct lock *lock);
/* wake up all threads that are waiting on the condition variable cv. be sure to
* check that the calling thread had acquired lock when this call is made. */
void cv_broadcast(struct cv *cv, struct lock *lock);
#endif /* _THREAD_H_ */