signal_fsem,Increments the value of the fast semaphore associated with the specified process.Phantom processes do not have fast semaphores.
对于非中断进程,
pcb->fsem_value = ++value;
if (value == 0 && (pcb->state & ST_FSEM))
调用该函数fsem值就会加加,加加之后如果值等于0,并且之前进程(PRIO进程)状态是ST_FSEM,那么就可以设置进程为非waiting状态。
#define ST_READY (0x04U)
#define ST_RECEIVE (0x04U)
#define ST_DELAY (0x08U)
#define ST_SEM (0x10U)
#define ST_FSEM (0x20U)
#define ST_INTERCEPT (0x40U)
#define ST_STOPPED (0x80U)
#define ST_WAITING (ST_RECEIVE | ST_DELAY | ST_SEM | ST_FSEM)
ST_WAITING = 0x3C,所以~ ST_WAITING = 0x03 <ST_READY,所以可以执行SWAP_IF_NECESSARY(pcb)。
#define SWAP_IF_NECESSARY(pcb) odo_swap_if_necessary(pcb),参数pcb就是释放了信号量的进程,signal_fsem函数释放了pid进程的信号量,所以这里判断是否需要进行切换到释放了信号量的进程。
odo_swap_if_necessary,在该函数中将会(可能)切换到参数pcb进程。当参数pcb进程 make_ready后,该进程就会被分发,如果参数pcb进程的优先级高于当前正在执行的进程(odo_sys.current_ni),并且current_ni进程是个normal进程(即PRIO进程),就调用odo_do_swap函数进行切换。否则稍后swap:
1,MAKE_READY
rqueue是pcb的ready进程的头。
QQUEUE_ADD_LAST(head, me),作用是将me插到head之前,me就成为了新的head。
me就等于pcb->next.ready,即已经释放了fsem的进程,即swap_if函数的参数。
pcb结构中的next.ready,就是next entry in the ready_queue.仅用于PRIO进程。
PRIOMAKS_SET(pcb):设置odo_sys.priomask.mask 相应位为1。
2,如果dispatch_lock_count != 0,表示进程分发被锁住了,暂时不能做切换。就要通过DISPATCH_REQUEST请求分
发了:
/* DISPATCH_REQUEST:
* Used when a swap can not be performed (if current process is an interrupt process).
//如当前是中断进程时,就不能swap。
* Sets the odo_sys.dispatch_request flag */
#define DISPATCH_REQUEST() odo_sys.dispatch_request = 1
3,如果dispatch_lock_count = 0,并且要切换的进程的优先级高,就通过DISPATCH_LOCK函数,先锁住分发,然后
执行odo_do_sawp做切换。
/* DISPATCH_LOCK:
* Can only be used with interrupt disabled.
*/
#define DISPATCH_LOCK() odo_sys.dispatch_lock_count +=0x100
加上2中if的判断目的是如果current_ni已经在odo_do_swap被抢占,就不能执行odo_do_swap再做切换了。好在odo_swap_if_nessary函数中会在odo_do_swap前,设置dispatch_lock_count += 0x100,这样下次执行do_swap_if_nessary函数时,就只执行if语句了,不会再做swap了。所以这里代码做了保护,虽然这种可能性很低,因为一个core只能同时有一个进程执行。(每个core都有自己的odo_sys变量)。