diff options
author | root <root@ubuntu-qemu.(none)> | 2013-05-06 00:35:28 -0400 |
---|---|---|
committer | root <root@ubuntu-qemu.(none)> | 2013-05-06 00:35:28 -0400 |
commit | ff4b3e6b1353fed910dd0532186dc53d648bd2de (patch) | |
tree | 37c35c926cfc566aefaa81ca71449187e4ebb14b | |
parent | 0947d7543a9dd0b196d6fedd510422a733908b40 (diff) |
More progress.
-rw-r--r-- | bin/.rwrnlp.c.swp | bin | 20480 -> 0 bytes | |||
-rw-r--r-- | bin/rwrnlp.c | 24 | ||||
-rw-r--r-- | include/spinlocks.h | 6 | ||||
-rw-r--r-- | multi.csv | 6 | ||||
-rw-r--r-- | simple.csv | 4 | ||||
-rw-r--r-- | src/spinlocks.c | 101 | ||||
-rw-r--r-- | test.csv | 3 |
7 files changed, 98 insertions, 46 deletions
diff --git a/bin/.rwrnlp.c.swp b/bin/.rwrnlp.c.swp deleted file mode 100644 index 207edbb..0000000 --- a/bin/.rwrnlp.c.swp +++ /dev/null | |||
Binary files differ | |||
diff --git a/bin/rwrnlp.c b/bin/rwrnlp.c index 157fcf4..c3221d8 100644 --- a/bin/rwrnlp.c +++ b/bin/rwrnlp.c | |||
@@ -228,6 +228,8 @@ void* rt_thread(void *tcontext) | |||
228 | 228 | ||
229 | CALL( set_rt_task_param(gettid(), ¶m) ); | 229 | CALL( set_rt_task_param(gettid(), ¶m) ); |
230 | 230 | ||
231 | fprintf(stderr, "Thread %d on processor %d\n", gettid(), ctx->processor); | ||
232 | |||
231 | /***** | 233 | /***** |
232 | * 2) Transition to real-time mode. | 234 | * 2) Transition to real-time mode. |
233 | */ | 235 | */ |
@@ -272,7 +274,7 @@ static int loop_for(double exec_time, double emergency_exit) | |||
272 | if (emergency_exit && wctime() > emergency_exit) { | 274 | if (emergency_exit && wctime() > emergency_exit) { |
273 | /* Oops --- this should only be possible if the execution time tracking | 275 | /* Oops --- this should only be possible if the execution time tracking |
274 | * is broken in the LITMUS^RT kernel. */ | 276 | * is broken in the LITMUS^RT kernel. */ |
275 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", getpid()); | 277 | fprintf(stderr, "!!! rtspin/%d emergency exit!\n", gettid()); |
276 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); | 278 | fprintf(stderr, "Something is seriously wrong! Do not ignore this.\n"); |
277 | break; | 279 | break; |
278 | } | 280 | } |
@@ -295,21 +297,21 @@ static int job(struct thread_context *ctx, double program_end) | |||
295 | loop_for(ncs_length, program_end + 1); | 297 | loop_for(ncs_length, program_end + 1); |
296 | 298 | ||
297 | if(ctx->type == read_req){ | 299 | if(ctx->type == read_req){ |
298 | printf("%d read locking...\n", getpid()); | 300 | printf("%d:%d read locking...\n", __sync_fetch_and_add(&events,1), gettid()); |
299 | rwrnlp_read_lock(&rw_lock, ctx->resources, ctx->processor); | 301 | rwrnlp_read_lock(&rw_lock, ctx->resources, ctx->processor); |
300 | printf("%d read CS...\n", getpid()); | 302 | printf("%d:%d read CS...\n", __sync_fetch_and_add(&events, 1), gettid()); |
301 | loop_for(ctx->cs_length, program_end + 1); | 303 | loop_for(ctx->cs_length*S_PER_MS, program_end + 1); |
302 | printf("%d read unlocking...\n", getpid()); | 304 | printf("%d:%d read unlocking...\n", __sync_fetch_and_add(&events,1), gettid()); |
303 | rwrnlp_read_unlock(&rw_lock, ctx->processor); | 305 | rwrnlp_read_unlock(&rw_lock, ctx->processor); |
304 | printf("%d ncs...\n", getpid()); | 306 | printf("%d:%d ncs...\n", __sync_fetch_and_add(&events,1), gettid()); |
305 | }else{ | 307 | }else{ |
306 | printf("%d write locking...\n", getpid()); | 308 | printf("%d:%d write locking %lu\n", __sync_fetch_and_add(&events,1), gettid(), ctx->resources); |
307 | rwrnlp_write_lock(&rw_lock, ctx->resources, ctx->processor); | 309 | rwrnlp_write_lock(&rw_lock, ctx->resources, ctx->processor); |
308 | printf("%d write CS...\n", getpid()); | 310 | printf("%d:%d write CS...\n", __sync_fetch_and_add(&events,1), gettid()); |
309 | loop_for(ctx->cs_length, program_end + 1); | 311 | loop_for(ctx->cs_length*S_PER_MS, program_end + 1); |
310 | printf("%d write unlocking...\n", getpid()); | 312 | printf("%d:%d write unlocking...\n", __sync_fetch_and_add(&events,1), gettid()); |
311 | rwrnlp_write_unlock(&rw_lock, ctx->processor); | 313 | rwrnlp_write_unlock(&rw_lock, ctx->processor); |
312 | printf("%d ncs...\n", getpid()); | 314 | printf("%d:%d ncs...\n", __sync_fetch_and_add(&events,1), gettid()); |
313 | } | 315 | } |
314 | 316 | ||
315 | 317 | ||
diff --git a/include/spinlocks.h b/include/spinlocks.h index 9871685..d83a0d8 100644 --- a/include/spinlocks.h +++ b/include/spinlocks.h | |||
@@ -4,9 +4,11 @@ | |||
4 | #define NR_CPUS 4 | 4 | #define NR_CPUS 4 |
5 | #define NR_RESOURCES sizeof(resource_mask_t)*8 | 5 | #define NR_RESOURCES sizeof(resource_mask_t)*8 |
6 | 6 | ||
7 | extern int events; | ||
8 | |||
7 | typedef enum {read_req, write_req} request_type; | 9 | typedef enum {read_req, write_req} request_type; |
8 | typedef enum {waiting, acquired, entitled} request_status; | 10 | typedef enum {waiting, acquired, entitled} request_status; |
9 | typedef long resource_mask_t; | 11 | typedef unsigned long resource_mask_t; |
10 | 12 | ||
11 | typedef struct request_struct { | 13 | typedef struct request_struct { |
12 | resource_mask_t resources; | 14 | resource_mask_t resources; |
@@ -26,7 +28,7 @@ typedef struct rwrnlp_struct { | |||
26 | 28 | ||
27 | int enter[NR_CPUS]; | 29 | int enter[NR_CPUS]; |
28 | int leave[NR_CPUS]; | 30 | int leave[NR_CPUS]; |
29 | request* requests[NR_CPUS]; | 31 | request requests[NR_CPUS]; |
30 | 32 | ||
31 | request* wqueue[NR_RESOURCES][NR_CPUS]; | 33 | request* wqueue[NR_RESOURCES][NR_CPUS]; |
32 | unsigned int whead[NR_RESOURCES]; | 34 | unsigned int whead[NR_RESOURCES]; |
diff --git a/multi.csv b/multi.csv new file mode 100644 index 0000000..acf5a3c --- /dev/null +++ b/multi.csv | |||
@@ -0,0 +1,6 @@ | |||
1 | 0 10.0 17.0 3.0 0 1 | ||
2 | 1 12.0 19.0 8.0 0 3 | ||
3 | 3 17.0 23.0 8.0 1 4 | ||
4 | 2 10.0 17.0 3.0 0 5 | ||
5 | 1 12.0 29.0 8.0 1 1 | ||
6 | 3 17.0 21.0 8.0 1 4 | ||
diff --git a/simple.csv b/simple.csv new file mode 100644 index 0000000..6a166b1 --- /dev/null +++ b/simple.csv | |||
@@ -0,0 +1,4 @@ | |||
1 | 0 10.0 17.0 3.0 0 3 | ||
2 | 1 12.0 19.0 8.0 1 2 | ||
3 | 2 17.0 23.0 8.0 1 1 | ||
4 | 3 17.0 23.0 8.0 1 3 | ||
diff --git a/src/spinlocks.c b/src/spinlocks.c index 16e1f06..9847aac 100644 --- a/src/spinlocks.c +++ b/src/spinlocks.c | |||
@@ -2,10 +2,13 @@ | |||
2 | #include <stdio.h> | 2 | #include <stdio.h> |
3 | #include <string.h> | 3 | #include <string.h> |
4 | 4 | ||
5 | #include "litmus.h" | ||
5 | #include "spinlocks.h" | 6 | #include "spinlocks.h" |
6 | 7 | ||
7 | #define NR_RESOURCES sizeof(resource_mask_t)*8 | 8 | #define NR_RESOURCES sizeof(resource_mask_t)*8 |
8 | 9 | ||
10 | int events; | ||
11 | |||
9 | void spin_init(spinlock_t *lock){ | 12 | void spin_init(spinlock_t *lock){ |
10 | lock->serving = 0; | 13 | lock->serving = 0; |
11 | lock->next_ticket = 0; | 14 | lock->next_ticket = 0; |
@@ -13,6 +16,8 @@ void spin_init(spinlock_t *lock){ | |||
13 | 16 | ||
14 | void spin_lock(spinlock_t *lock){ | 17 | void spin_lock(spinlock_t *lock){ |
15 | int ticket = __sync_fetch_and_add(&(lock->next_ticket), 1); | 18 | int ticket = __sync_fetch_and_add(&(lock->next_ticket), 1); |
19 | printf("%d:%d waiting for ticket %d serving %d\n", | ||
20 | __sync_fetch_and_add(&events,1), gettid(), ticket, lock->serving); | ||
16 | while(lock->serving != ticket); | 21 | while(lock->serving != ticket); |
17 | } | 22 | } |
18 | 23 | ||
@@ -23,6 +28,7 @@ void spin_unlock(spinlock_t *lock){ | |||
23 | void rwrnlp_init(rwrnlp *lock) | 28 | void rwrnlp_init(rwrnlp *lock) |
24 | { | 29 | { |
25 | int i; | 30 | int i; |
31 | events = 0; | ||
26 | lock->wlocked = 0; | 32 | lock->wlocked = 0; |
27 | lock->wentitled = 0; | 33 | lock->wentitled = 0; |
28 | lock->unavailable = 0; | 34 | lock->unavailable = 0; |
@@ -43,43 +49,57 @@ void rwrnlp_init(rwrnlp *lock) | |||
43 | 49 | ||
44 | void rwrnlp_read_lock(rwrnlp *lock, resource_mask_t resources, int processor) | 50 | void rwrnlp_read_lock(rwrnlp *lock, resource_mask_t resources, int processor) |
45 | { | 51 | { |
46 | request req; | 52 | request *req; |
47 | req.resources = resources; | 53 | |
48 | req.type = read_req; | 54 | enter_np(); |
49 | req.status = waiting; | 55 | |
56 | req = &lock->requests[processor]; | ||
57 | req->resources = resources; | ||
58 | req->type = read_req; | ||
59 | req->status = waiting; | ||
50 | lock->enter[processor]+=1; | 60 | lock->enter[processor]+=1; |
51 | lock->requests[processor] = &req; | 61 | |
62 | printf("%d:%d rwrnlp_read_lock %lu\n",__sync_fetch_and_add(&events,1), gettid(), req->resources); | ||
52 | 63 | ||
53 | spin_lock(lock->state); | 64 | spin_lock(lock->state); |
54 | if((req.resources & lock->unavailable) == 0){ | 65 | if((req->resources & lock->unavailable) == 0){ |
55 | req.status = acquired; | 66 | req->status = acquired; |
56 | } | 67 | } |
57 | spin_unlock(lock->state); | 68 | spin_unlock(lock->state); |
58 | 69 | ||
59 | if(req.status != acquired){ | 70 | if(req->status != acquired){ |
60 | while((req.resources & lock->wentitled) != 0); | 71 | printf("%d:%d waiting to become entitled\n",__sync_fetch_and_add(&events,1), gettid()); |
61 | req.status = entitled; | 72 | while((req->resources & lock->wentitled) != 0); |
62 | while((req.resources & lock->wlocked) != 0); | 73 | req->status = entitled; |
74 | printf("%d:%d waiting to acquire\n", __sync_fetch_and_add(&events,1), gettid()); | ||
75 | while((req->resources & lock->wlocked) != 0); | ||
63 | } | 76 | } |
77 | |||
78 | printf("%d:%d reader satisfied\n", __sync_fetch_and_add(&events,1), gettid()); | ||
64 | } | 79 | } |
65 | 80 | ||
66 | void rwrnlp_write_lock(rwrnlp *lock, resource_mask_t resources, int processor) | 81 | void rwrnlp_write_lock(rwrnlp *lock, resource_mask_t resources, int processor) |
67 | { | 82 | { |
68 | int r,i,start,end; | 83 | int r,i,start,end; |
69 | request req; | 84 | request *req, *contender; |
70 | request* contender; | ||
71 | resource_mask_t tmp = resources; | 85 | resource_mask_t tmp = resources; |
72 | req.resources = resources; | 86 | |
73 | req.type = read_req; | 87 | enter_np(); |
74 | req.status = waiting; | 88 | |
89 | printf("%d:%d rwrnlp_write_lock\n", __sync_fetch_and_add(&events,1), gettid()); | ||
90 | |||
91 | req = &lock->requests[processor]; | ||
92 | |||
93 | req->resources = resources; | ||
94 | req->type = write_req; | ||
95 | req->status = waiting; | ||
75 | lock->enter[processor]+=1; | 96 | lock->enter[processor]+=1; |
76 | lock->requests[processor] = &req; | ||
77 | 97 | ||
78 | spin_lock(lock->enqueue); | 98 | spin_lock(lock->enqueue); |
79 | r = ffsl(tmp); | 99 | r = ffsl(tmp); |
80 | while(r != 0){ | 100 | while(r != 0){ |
81 | r = r-1; // ffsl gives 1-indexed, since 0 is the return value for 0. | 101 | r = r-1; // ffsl gives 1-indexed, since 0 is the return value for 0. |
82 | lock->wqueue[r][lock->wtail[r]] = &req; | 102 | lock->wqueue[r][lock->wtail[r]] = req; |
83 | lock->wtail[r] = (lock->wtail[r] + 1) % NR_CPUS; | 103 | lock->wtail[r] = (lock->wtail[r] + 1) % NR_CPUS; |
84 | tmp &= ~(1<<r); | 104 | tmp &= ~(1<<r); |
85 | r = ffsl(tmp); | 105 | r = ffsl(tmp); |
@@ -87,53 +107,74 @@ void rwrnlp_write_lock(rwrnlp *lock, resource_mask_t resources, int processor) | |||
87 | spin_unlock(lock->enqueue); | 107 | spin_unlock(lock->enqueue); |
88 | 108 | ||
89 | tmp = resources; | 109 | tmp = resources; |
110 | r = ffsl(tmp); | ||
90 | while(r != 0){ | 111 | while(r != 0){ |
91 | r = r-1; | 112 | r = r-1; |
92 | while(lock->wqueue[r][lock->whead[r]] != &req); | 113 | printf("%d:%d write waiting to become head of %d\n", __sync_fetch_and_add(&events,1), gettid(), r); |
114 | while(lock->wqueue[r][lock->whead[r]] != req); | ||
93 | tmp &= ~(1<<r); | 115 | tmp &= ~(1<<r); |
94 | r = ffsl(tmp); | 116 | r = ffsl(tmp); |
95 | } | 117 | } |
96 | 118 | ||
97 | spin_lock(lock->state); | 119 | spin_lock(lock->state); |
98 | lock->unavailable |= req.resources; | 120 | lock->unavailable |= req->resources; |
99 | req.status = entitled; | 121 | req->status = entitled; |
100 | spin_unlock(lock->state); | 122 | spin_unlock(lock->state); |
101 | 123 | ||
102 | for(i = 0; i < NR_CPUS; i++){ | 124 | for(i = 0; i < NR_CPUS; i++){ |
103 | if(i != processor){ | 125 | if(i != processor){ |
104 | start = lock->enter[i]; | 126 | start = lock->enter[i]; |
105 | contender = lock->requests[i]; | 127 | contender = &lock->requests[i]; |
106 | end = lock->leave[i]; | 128 | end = lock->leave[i]; |
107 | if(start <= end || | 129 | if(start <= end || |
108 | contender->type == write_req || | 130 | contender->type == write_req || |
109 | contender->status == waiting || | 131 | contender->status == waiting || |
110 | (contender->resources & req.resources) == 0) | 132 | (contender->resources & req->resources) == 0) |
111 | continue; | 133 | continue; |
112 | 134 | ||
135 | printf("%d:%d waiting for reader on processor %d\n", __sync_fetch_and_add(&events,1), gettid(), i); | ||
113 | while(lock->leave[i] < start); | 136 | while(lock->leave[i] < start); |
114 | } | 137 | } |
115 | } | 138 | } |
116 | 139 | ||
117 | spin_lock(lock->state); | 140 | spin_lock(lock->state); |
118 | lock->wentitled &= ~req.resources; | 141 | lock->wentitled &= ~(req->resources); |
119 | lock->wlocked |= req.resources; | 142 | lock->wlocked |= req->resources; |
120 | spin_unlock(lock->state); | 143 | spin_unlock(lock->state); |
144 | |||
145 | printf("%d:%d writer satisfied\n", __sync_fetch_and_add(&events,1), gettid()); | ||
121 | } | 146 | } |
122 | 147 | ||
123 | void rwrnlp_read_unlock(rwrnlp *lock, int processor) | 148 | void rwrnlp_read_unlock(rwrnlp *lock, int processor) |
124 | { | 149 | { |
125 | lock->leave[processor] += 1; | 150 | lock->leave[processor] += 1; |
126 | lock->requests[processor] = NULL; | 151 | printf("%d:%d rwrnlp_read_unlock\n", __sync_fetch_and_add(&events,1), gettid()); |
152 | exit_np(); | ||
127 | } | 153 | } |
128 | 154 | ||
129 | void rwrnlp_write_unlock(rwrnlp *lock, int processor) | 155 | void rwrnlp_write_unlock(rwrnlp *lock, int processor) |
130 | { | 156 | { |
131 | request *req = lock->requests[processor]; | 157 | int r; |
158 | request *req = &lock->requests[processor]; | ||
159 | resource_mask_t tmp = req->resources; | ||
160 | |||
161 | printf("%d:%d rwrnlp_write_unlock\n", __sync_fetch_and_add(&events,1), gettid()); | ||
162 | |||
132 | lock->leave[processor] += 1; | 163 | lock->leave[processor] += 1; |
133 | lock->requests[processor] = NULL; | ||
134 | 164 | ||
135 | spin_lock(lock->state); | 165 | spin_lock(lock->state); |
136 | lock->wlocked &= ~req->resources; | 166 | r = ffsl(tmp); |
137 | lock->unavailable &= ~req->resources; | 167 | while(r != 0){ |
168 | r = r-1; // ffsl gives 1-indexed, since 0 is the return value for 0. | ||
169 | lock->whead[r] = (lock->whead[r] + 1) % NR_CPUS; | ||
170 | tmp &= ~(1<<r); | ||
171 | r = ffsl(tmp); | ||
172 | } | ||
173 | lock->wlocked &= ~(req->resources); | ||
174 | lock->unavailable &= ~(req->resources); | ||
138 | spin_unlock(lock->state); | 175 | spin_unlock(lock->state); |
176 | |||
177 | printf("%d:%d write unlocked %lu\n", __sync_fetch_and_add(&events,1), gettid(), req->resources); | ||
178 | printf("unavailable %lu\nwentitled %lu\nwlocked %lu\n", lock->unavailable, lock->wentitled, lock->wlocked); | ||
179 | exit_np(); | ||
139 | } | 180 | } |
diff --git a/test.csv b/test.csv deleted file mode 100644 index 37bf459..0000000 --- a/test.csv +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | 0 10.0 100.0 1.0 0 0110 | ||
2 | 1 10.0 100.0 1.0 0 0110 | ||
3 | 3 10.0 100.0 1.0 1 0010 | ||