سلام ، ماشالا دوستان خیلی پیشرفت کردن من هنوز باسمافور ها مشکل دارم یعنی بعد اینکه مولتی پروسسور کردم کرنلو باهاش مواجه شدم
اول کد رو ببینین تا بگم مشکل کجاست
/*
* Semaphore v 1.0.0
* Create a semaphore by (struct semaphore ) then using sem_wait(struct semaphore *) in first
* For acquiring and sem_signal(struct semaphore *) for release it.
* Example :
* struct semaphore s;
* initsem(&s, "mysem");
* sem_wait(&s);
* ...
* sem_signal(&s);
*/
#include <types.h>
#include <defs.h>
#include <param.h>
#include <memlayout.h>
#include <mmu.h>
#include <x86.h>
#include <queue.h>
#include <proc.h>
#include <spinlock.h>
#include <semaphore.h>
void
initsem(struct semaphore *sem, char* name){
memset(sem, 0, sizeof(struct semaphore));
// if count = 0 all process change to sleep
// then count to be equal by 1.
sem->count = 1;
sem->wait = 0;
initlock(&sem->lock, name);
queue_init ( &sem->Queue );
}
void
sem_wait(struct semaphore *sem){
acquire(&sem->lock);
if ( proc )
{
if(sem->count > 0)
{
sem->count--;
}else{
if(!sem->count){
struct proc * p;
if((p = queue_remove ( &sem->Queue, FIRST, NULL ))){
cprintf("----------> force wakeup %x \n", p);
wakeup(p);
}
}
queue_append ( &sem->Queue, proc, &proc->SHeader );
cprintf("----------> sleep %x \n", proc);
sleep(proc, &sem->lock);
cprintf("----------> wakeup1 \n");
}
}
release(&sem->lock);
}
void
sem_signal(struct semaphore *sem){
acquire(&sem->lock);
if(proc)
{
if(!sem->count){
sem->count++;
}else{
struct proc * p;
while(!(p = queue_remove ( &sem->Queue, FIRST, NULL )));
cprintf("----------> wakeup %x \n", p);
wakeup(p);
}
}
release(&sem->lock);
}
بزارین اول بگم این چطوری کار میکنه ، وقتی اولین پروسه از سمافور wait میگذره مقدار شمارشگر یکی میاد پایین یعنی از حالت اولیه یک میشه صفر و پروسه بعدی که میاد سمافور اونو به لیست اضافه میکنه و به حالت خواب میبره و مشکل اینجاست که پروسه اولی از سمافور signal گذشته و مقدار شمارشگرو هم به ۱ برگردونده و دیگه هیچ پروسه ای نیست که این پروسه خواب رو بیدار کنه خب یه جور بنبست پیش اومده دیگه ، شاید بگین که اسپین لوک درست کار نکرده که در زمانی که پروسه داشته در سمافور به خواب میرفته اجازه داده که پروسه اول از سیگنال عبور کنه ولی اسپین ها درست کار میکنن و این به این خاطر هست که زمانی که به حالت خواب میرن باید سمافور ازاد بشه و بعد به حالت خواب بره و وقتی که پروسه بیدار شد دوباره قفل بشه و ادامه پیدا کنه
خب الان تیکه تیکه کد رو توضیح میدم تا بفهمین چی گفتم
void
sleep(void *chan, struct spinlock *lk){
if(proc == 0)
panic("sleep");
if(lk == 0)
panic("sleep without lk");
اینجا ما قفل سمافور رو ازاد میکنیم تا به حالت خواب بره
if(lk != &ptable.lock){
acquire(&ptable.lock);
release(lk);
}
// Go to sleep.
proc->chan = chan;
// Set quantum times for next start
uint laststart = proc->LastStarted;
proc->LastStarted = proc->Quantum;
proc->Quantum = ticks - laststart;
اینجا پروسه به خواب میره
struct proc *next, *backup;
next = queue_get(&g_RunningQueue, FIRST);
while(next){
backup = queue_get_next(&next->ProcQHeader);
if(next == proc)
{
next->state = SLEEPING;
next = queue_remove ( &g_RunningQueue, FIRST, &next->ProcQHeader );
queue_append ( &g_SleepingQueue, next, &next->ProcQHeader );
}
next = backup;
}
اینجا پروسه سویچ میشه به پروسه دیگه
sched();
// Tidy up.
proc->chan = 0;
اینجا دوباره سمافور قفل میشه
// Reacquire original lock.
if(lk != &ptable.lock){ //DOC: sleeplock2
release(&ptable.lock);
acquire(lk);
}
}
خب حالا بریم سر کد سمافور
void
sem_wait(struct semaphore *sem){
acquire(&sem->lock);
if ( proc )
{
if(sem->count > 0)
{
sem->count--;
}else{
if(!sem->count){
struct proc * p;
if((p = queue_remove ( &sem->Queue, FIRST, NULL ))){
cprintf("----------> force wakeup %x \n", p);
wakeup(p);
}
}
queue_append ( &sem->Queue, proc, &proc->SHeader );
cprintf("----------> sleep %x \n", proc);
اینجا به حالت خواب میره
sleep(proc, &sem->lock);
وقتی بیدار میشه از اینجا ادامه پیدا میکنه
cprintf("----------> wakeup1 \n");
}
}
release(&sem->lock);
}