Mercurial > hg > Game > Cerium
changeset 1186:4c209dd223cd draft
fix MailManager and Semaphore
author | Daichi TOMA |
---|---|
date | Mon, 04 Jul 2011 14:11:26 +0900 |
parents | 5a9bee9cc8c9 |
children | d4311f83377a |
files | TaskManager/Makefile.parallel TaskManager/kernel/ppe/MailManager.cc TaskManager/kernel/ppe/MailManager.h TaskManager/kernel/ppe/Sem.cc TaskManager/kernel/ppe/Sem.h TaskManager/test/MailManagerTest.cc TaskManager/test/Makefile |
diffstat | 7 files changed, 82 insertions(+), 64 deletions(-) [+] |
line wrap: on
line diff
--- a/TaskManager/Makefile.parallel Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/Makefile.parallel Mon Jul 04 14:11:26 2011 +0900 @@ -1,5 +1,5 @@ include ./Makefile.def -TARGET = libParallelManager.a +TARGET = libFifoManager.a CFLAGS += -DHAS_POSIX_MEMALIGN .SUFFIXES: .cc .o
--- a/TaskManager/kernel/ppe/MailManager.cc Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/kernel/ppe/MailManager.cc Mon Jul 04 14:11:26 2011 +0900 @@ -17,77 +17,46 @@ calc_mask(qsize); queue = Newq(memaddr,size); - mutex_s = new pthread_mutex_t; //sendのロック用 - mutex_r = new pthread_mutex_t; //recvのロック用 - pthread_mutex_init(mutex_s, NULL); - pthread_mutex_init(mutex_r, NULL); - - remain = new Sem(0); //queue内のアイテム数を管理 + queue_remain = new Sem(size-1); //queue内にあと入る数 + queue_count = new Sem(0); //queue内に現在入っている数 } MailManager::~MailManager() { free(queue); - - pthread_mutex_destroy(mutex_s); - pthread_mutex_destroy(mutex_r); - - delete mutex_s; - delete mutex_r; - delete remain; + delete queue_remain; + delete queue_count; } int MailManager::count() { - return (write+size-read)&mask; -} - -void -MailManager::extend() -{ - memaddr *newq = Newq(memaddr,size*2); - unsigned int i = 0; - while(i<size) { - newq[i++] = queue[read++]; - read &= mask; - } - read = 0; write = i; - calc_mask(size*2); - free(queue); - queue = newq; + return queue_count->count(); } void MailManager::send(memaddr data) { - pthread_mutex_lock(mutex_s); + queue_remain->sem_p(); //資源-1 queue[write++] = data; + //maskの範囲を超えた場合、0に戻す write &= mask; - if (write==read) { - extend(); - } - pthread_mutex_unlock(mutex_s); - remain->sem_v(); //資源を解放 + queue_count->sem_v(); //資源+1 } memaddr MailManager::recv() { - pthread_mutex_lock(mutex_r); + queue_count->sem_p(); //資源-1 - remain->sem_p(); //資源の確保 memaddr data; - if (count()>0) { data = queue[read++]; read &= mask; - } else { - data = 0; - } - pthread_mutex_unlock(mutex_r); + + queue_remain->sem_v(); //資源+1 return data; }
--- a/TaskManager/kernel/ppe/MailManager.h Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/kernel/ppe/MailManager.h Mon Jul 04 14:11:26 2011 +0900 @@ -20,9 +20,8 @@ private: /* variables */ memaddr *queue; - pthread_mutex_t *mutex_s; - pthread_mutex_t *mutex_r; - SemPtr remain; + SemPtr queue_remain; + SemPtr queue_count; unsigned int size; unsigned int read; unsigned int write;
--- a/TaskManager/kernel/ppe/Sem.cc Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/kernel/ppe/Sem.cc Mon Jul 04 14:11:26 2011 +0900 @@ -28,7 +28,9 @@ while(sem->value == 0) { pthread_cond_wait(&sem->cond, &sem->mutex); } - sem->value--; //資源の確保 + //atomic + //sem->value--; //資源の確保 + __sync_fetch_and_sub(&sem->value,1); pthread_mutex_unlock(&sem->mutex); } @@ -38,9 +40,20 @@ Sem::sem_v() { pthread_mutex_lock(&sem->mutex); - sem->value++; //資源の解放 - pthread_mutex_unlock(&sem->mutex); + //atomic + //sem->value++; //資源の解放 + __sync_fetch_and_add(&sem->value,1); //資源の解放を知らせる pthread_cond_signal(&sem->cond); + pthread_mutex_unlock(&sem->mutex); + } + +int +Sem::count() +{ + //semの値を返せばよい。 + //atomic + return sem->value; +}
--- a/TaskManager/kernel/ppe/Sem.h Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/kernel/ppe/Sem.h Mon Jul 04 14:11:26 2011 +0900 @@ -16,6 +16,7 @@ ~Sem(); void sem_p(); void sem_v(); + int count(); /* variables */ private: sem_t *sem;
--- a/TaskManager/test/MailManagerTest.cc Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/test/MailManagerTest.cc Mon Jul 04 14:11:26 2011 +0900 @@ -1,6 +1,11 @@ #include <stdio.h> #include "TaskManager/MailManager.h" +typedef struct _thread_arg { + MailManagerPtr m; + int size; +} thread_arg_t; + static void fail(const char *reason) { @@ -8,30 +13,62 @@ } static void +send_func(void *arg) +{ + thread_arg_t* targ = (thread_arg_t *)arg; + for(int i = 0; i < targ->size; i++) { + printf("send %d\n",i); + targ->m->send((memaddr)i); + } + return; +} + +static void +recv_func(void *arg) +{ + thread_arg_t* targ = (thread_arg_t *)arg; + for(int i = 0; i < targ->size; i++) { + if (targ->m->recv() != (memaddr)i) { + fail("read data fail\n"); + break; + } + printf("\t receive %d\n",i); + } + return; +} + +static void tester(MailManagerPtr m, int size) { + //送信者スレッド作成 + thread_arg_t starg; + starg.m = m; + starg.size = size; - for(int i=0;i<size;i++) { - m->send((memaddr)i); - } - for(int i=0;i<size;i++) { - if (m->count()==0) { - fail("early read fail\n"); break; - } - if (m->recv()!=(memaddr)i) { - fail("read data fail\n"); break; - } - } + pthread_t send; + pthread_create(&send, NULL, (void* (*)(void*))&send_func, (void*)&starg); + + //受信者スレッド作成 + thread_arg_t rtarg; + rtarg.m = m; + rtarg.size = size; + + pthread_t recv; + pthread_create(&recv, NULL, (void* (*)(void*))&recv_func, (void*)&rtarg); + + //終了待ち + pthread_join(send, NULL); + pthread_join(recv, NULL); } static void test1() { - MailManagerPtr m = new MailManager(); + MailManagerPtr m = new MailManager(2); tester(m,16); tester(m,32); tester(m,48); delete m; - MailManagerPtr m1 = new MailManager(40); + MailManagerPtr m1 = new MailManager(32); tester(m1,16); tester(m1,48); delete m1;
--- a/TaskManager/test/Makefile Tue Jun 28 17:51:11 2011 +0900 +++ b/TaskManager/test/Makefile Mon Jul 04 14:11:26 2011 +0900 @@ -6,8 +6,7 @@ $(TARGET) : -#LIBS += ../libFifoManager.a -LIBS += ../libParallelManager.a +LIBS += ../libFifoManager.a MailManagerTest : MailManagerTest.o $(CC) $(CFLAGS) -o $@ $? $(LIBS)