www.pudn.com > LFYOS.zip > p.c


#include"kernel.h" 
 
#define WRONG_THREAD_ID		-1 
#define WRONG_SEMAPHORE_ID	-2 
#define WRONG_THREAD_STATE	-3 
#define WRONG_CAPABILITY	-4 
 
int system_call_p(int thread_id,int semaphore_id, 
	int sleep_flag,int v_flag,struct capability *cap) 
{ 
	struct return_stack *rt; 
	struct thread *t; 
	struct process *pro; 
	int return_value; 
	int steps; 
 
	if(semaphore_id==0){ 
		semaphore_id=os->thread[thread_id].semaphore; 
		cap=&(os->semaphore[semaphore_id].capability); 
	} 
	return_value=p(thread_id,semaphore_id,sleep_flag,TRUE,cap); 
	if(return_value<0) 
		return return_value; 
	if(!v_flag) 
		return return_value; 
	t=&(os->thread[thread_id]); 
	rt=&(t->return_stack[t->return_stack_top-1]); 
	if(rt->process_p_flag) 
		return return_value; 
	pro=&(os->process[rt->current_process]); 
	if(pro->semaphore<=0) 
		return return_value; 
	steps=1; 
	cap=&(os->semaphore[pro->semaphore].capability); 
	if(system_call_v(pro->semaphore,&steps,cap)>=0) 
		rt->process_p_flag=TRUE; 
	return return_value; 
} 
 
int p(int thread_id,int semaphore_id, 
	int sleep_flag,int result_flag,struct capability *cap) 
{ 
	struct thread *t; 
	struct semaphore *s; 
 
	if((thread_id<0)||(thread_id>=THREAD_NUMBER)) 
		return(WRONG_THREAD_ID); 
	t=&(os->thread[thread_id]); 
	if((semaphore_id<0)||(semaphore_id>=SEMAPHORE_NUMBER)) 
		return WRONG_SEMAPHORE_ID; 
	s=&(os->semaphore[semaphore_id]); 
	if(s->process<0) 
		return WRONG_SEMAPHORE_ID; 
	if((t->state!=RUN)&&(t->state!=READY)) 
		return WRONG_THREAD_STATE; 
	if(!KERNEL_COMPARE_CAPABILITY(s->capability,(*cap))) 
		return WRONG_CAPABILITY; 
 
	s->value--; 
	if(s->value>=0) return 1; 
 
	if(!sleep_flag) 
		{s->value++;return 0;} 
	if(s->thread_ring<0){ 
			t->sem_front=thread_id; 
			t->sem_back=thread_id; 
			s->thread_ring=thread_id; 
		} 
	else{ 
		t->sem_front=s->thread_ring; 
		t->sem_back=os->thread[s->thread_ring].sem_back; 
		os->thread[t->sem_front].sem_back=thread_id; 
		os->thread[t->sem_back].sem_front=thread_id; 
	} 
	t->sleep_semaphore=semaphore_id; 
	remove_from_heap(thread_id); 
	t->set_v_operation_result_flag=result_flag; 
	return 0; 
}