📄 sync.c
字号:
/** * Copyright (c) 2006-2008 iWESUN (ShenZhen) Inf. * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. * * This file is part of the AvrcX MTOS * * Author: Winter Hu <winter.hu@gmail.com> * Create: Nov 27, 2006 */#include "sync.h"#include "scheduler.h"/** * Currently executing task swap out and put into BlockedQueue of * semaphore */void NAKED asleep(void);/** * Resumes tasks which are ready status from BlockedQueue of semaphore * * @param LinkedList*, The pointer to the BlockedQueue */void wakeup(void);/** * Set value of Semaphore * * @param Semaphore*, The pointer to the Semaphore monitor * @param signed char, The value of semaphore */INTERFACE void set_semaphore(Semaphore* sem, signed char sema){ sem->sema = sema;}/** * Reset Event to un-trigger status * User MUST invoke this method to reset Event monitor after wakeup * * @param Event*, The pointer to the Event monitor * @see void triggerEvent(Event*) */INTERFACE void reset_event(Event* event){ event->sema = 0;}/** * P primitive of the Semaphore * If --sema < 0, the caller will be swaped to BlockedQueue * * @param Semaphore*, The pointer to the Semaphore */INTERFACE void P(Semaphore* sem){ into_critical(); /* Because Event only has two status fired or unfired */ sem->sema = (sem->type == TYPE_EVENT) ? -1 : sem->sema-1; if (sem->sema < 0 && (kernel.SysLevel == USER_MODE)){ // TODO: asleep(sem->BlockedQueue); kernel.BlockedQueue = &(sem->BlockedQueue); asleep(); } exit_critical();}/** * V primitive of the Semaphore * If ++sema <= 0, the FIRST process in BlockedQueue will be wakeup * * @param Semaphore*, The pointer to the Semaphore monitor */INTERFACE void V(Semaphore* sem){ into_critical(); /* Because Event only has two status fired or unfired */ sem->sema = (sem->type == TYPE_EVENT) ? 0 : sem->sema+1; if (sem->sema <= 0){ // TODO: wakeup(sem->BlockedQueue); kernel.BlockedQueue = &(sem->BlockedQueue); wakeup(); } exit_critical();}/** * Release Mutex monitor, the FIRST process in BlockedQueue will be wakeup * * @param Mutex*, The pointer to the Mutex monitor * @see void waitObject(Monitor*) */INTERFACE void release_mutex(Mutex* mutex){ V(mutex);}/** * Trigger Event monitor, ALL processes in BlockedQueue could be wakeup, * User MUST reset Event monitor obviously. * * @param Event*, The pointer to the Event monitor * @see void waitObject(Monitor*) * @see void resetEvent(Event*) */INTERFACE void trigger_event(Event* event){ V(event);}/** * The caller maybe blocked in the BlockedQueue until the monitor object is * obtainable. * * @param Monitor*, The pointer to the Semaphore, Mutex or Event * @see void V(Semaphore*) * @see void releaseMutex(Mutex*) * @see void triggerEvent(Event*) */INTERFACE void wait_object(Monitor* mon){ P(mon);}/** * The caller blocked in the BlockedQueue until the monitor object is * obtainable or the specified time is timeout. * * @param Monitor*, The pointer to the Semaphore, Mutex, or Event * @param unsinged int, The timeout in ticks, 0 is never timeout. * @return unsigned char, 0, the monitor is obtainable. 1, timeout */INTERFACE unsigned char wait_object_with_timeout(Monitor* mon, unsigned int timeout){ into_critical(); PCB* pcb = (PCB*)(kernel.Running->pData); pcb->timer.ticks = timeout; P(mon); // Here, I wakeup into_critical(); unsigned char status = pcb->status & TASK_BLOCK; // Because the task in BlockedQueue and TimerQueue, so must remove from // another queue after wakeup if (status == 0){ PCB* pcb = (PCB*)(kernel.Running->pData); remove(&(kernel.TimerQueue), &(pcb->tid)); }else{ remove(&(mon->BlockedQueue), kernel.Running); status = 1; } exit_critical(); return status;}/** * Currently executing task swap out and put into BlockedQueue of * semaphore */void asleep(void){ prologue(); PID* pid = kernel.Running; PCB* pcb = (PCB*)(pid->pData); // PID to TimerQueue if (pcb->timer.ticks > 0){ delay_task(pid, pcb->timer.ticks); } // PID to BlockedQueue pcb->status |= TASK_BLOCK; append(kernel.BlockedQueue, pid); swapping(); epilogue();}/** * Resumes tasks which are ready status from BlockedQueue of semaphore * * @see resumeTask * @param LinkedList*, The pointer to the BlockedQueue */void wakeup(void){ PID* pid = remove_first(kernel.BlockedQueue); if (pid == NULL) return; PCB* pcb = (PCB*)(pid->pData); pcb->status &= ~TASK_BLOCK; if(kernel.SysLevel != USER_MODE){ // Already in kernel if (kernel.Running != NULL){ if (pcb->priority < ((PCB*)(kernel.Running->pData))->priority){ // Preemptived resume_task(kernel.Running); } } kernel.Running = pid; kernel.TmSlices= pcb->tmslices; }else{ // USER_MODE resume_task(pid); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -