00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <config.h>
00037
00038 #include <stdlib.h>
00039 #include <string.h>
00040
00041 #include "lwp.h"
00042 #include "lwpint.h"
00043
00044 struct lwp_rwlock {
00045
00046
00047
00048
00049
00050
00051 int count;
00052 struct lwpQueue rq;
00053 struct lwpQueue wq;
00054 char *name;
00055 };
00056
00057 struct lwp_rwlock *
00058 lwp_rwlock_create(char *name)
00059 {
00060 struct lwp_rwlock *rwlock;
00061
00062 rwlock = malloc(sizeof(*rwlock));
00063 if (!rwlock)
00064 return NULL;
00065
00066 memset(rwlock, 0, sizeof(*rwlock));
00067 rwlock->name = strdup(name);
00068 return rwlock;
00069 }
00070
00071 void
00072 lwp_rwlock_destroy(struct lwp_rwlock *rwlock)
00073 {
00074 if (CANT_HAPPEN(rwlock->count))
00075 return;
00076 free(rwlock->name);
00077 free(rwlock);
00078 }
00079
00080 void
00081 lwp_rwlock_wrlock(struct lwp_rwlock *rwlock)
00082 {
00083 if (rwlock->count) {
00084 lwpAddTail(&rwlock->wq, LwpCurrent);
00085 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for writing",
00086 rwlock->name);
00087 lwpReschedule();
00088 }
00089 CANT_HAPPEN(rwlock->count != 0);
00090 rwlock->count = -1;
00091 lwpStatus(LwpCurrent, "acquired rwlock %s for writing", rwlock->name);
00092 }
00093
00094 void
00095 lwp_rwlock_rdlock(struct lwp_rwlock *rwlock)
00096 {
00097 if (rwlock->count < 0 || rwlock->wq.head) {
00098 lwpStatus(LwpCurrent, "blocked to acquire rwlock %s for reading",
00099 rwlock->name);
00100 lwpAddTail(&rwlock->rq, LwpCurrent);
00101 lwpReschedule();
00102 }
00103 CANT_HAPPEN(rwlock->count < 0);
00104 rwlock->count++;
00105 lwpStatus(LwpCurrent, "acquired rwlock %s for reading", rwlock->name);
00106 }
00107
00108 void
00109 lwp_rwlock_unlock(struct lwp_rwlock *rwlock)
00110 {
00111 struct lwpProc *p;
00112
00113 lwpStatus(LwpCurrent, "unlocking rwlock %s", rwlock->name);
00114 if (CANT_HAPPEN(rwlock->count == 0))
00115 return;
00116 if (rwlock->count < 0)
00117 rwlock->count = 0;
00118 else
00119 rwlock->count--;
00120
00121 if (rwlock->count == 0 && rwlock->wq.head) {
00122 p = lwpGetFirst(&rwlock->wq);
00123 lwpStatus(p, "wake up next writer of rwlock %s", rwlock->name);
00124 } else if (rwlock->count >= 0 && rwlock->rq.head && !rwlock->wq.head) {
00125 p = lwpGetFirst(&rwlock->rq);
00126 lwpStatus(p, "wake up next reader of rwlock %s", rwlock->name);
00127 } else
00128 return;
00129
00130 lwpReady(p);
00131 if (LwpCurrent->pri < p->pri) {
00132 lwpStatus(LwpCurrent, "yielding to thread with higher priority");
00133 lwpYield();
00134 }
00135 }