tkernel_2/kernel/tkernel/src/task_sync.c | bare source | permlink (0.05 seconds) |
1: /* 2: *---------------------------------------------------------------------- 3: * T-Kernel 2.0 Software Package 4: * 5: * Copyright 2011 by Ken Sakamura. 6: * This software is distributed under the latest version of T-License 2.x. 7: *---------------------------------------------------------------------- 8: * 9: * Released by T-Engine Forum(http://www.t-engine.org/) at 2011/05/17. 10: * Modified by T-Engine Forum at 2012/10/24. 11: * Modified by TRON Forum(http://www.tron.org/) at 2015/06/01. 12: * 13: *---------------------------------------------------------------------- 14: */ 15: 16: /* 17: * task_sync.c (T-Kernel/OS) 18: * Task with Synchronize Function 19: */ 20: 21: #include <limits.h> 22: #include "kernel.h" 23: #include "task.h" 24: #include "wait.h" 25: #include "check.h" 26: 27: /* 28: * Suspend task 29: */ 30: SYSCALL ER _tk_sus_tsk( ID tskid ) 31: { 32: TCB *tcb; 33: TSTAT state; 34: ER ercd = E_OK; 35: 36: CHECK_TSKID(tskid); 37: CHECK_NONSELF(tskid); 38: 39: tcb = get_tcb(tskid); 40: 41: BEGIN_CRITICAL_SECTION; 42: state = (TSTAT)tcb->state; 43: if ( !task_alive(state) ) { 44: ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; 45: goto error_exit; 46: } 47: if ( tcb == ctxtsk && dispatch_disabled >= DDS_DISABLE ) { 48: ercd = E_CTX; 49: goto error_exit; 50: } 51: if ( tcb->suscnt == INT_MAX ) { 52: ercd = E_QOVR; 53: goto error_exit; 54: } 55: 56: /* Update suspend request count */ 57: ++tcb->suscnt; 58: 59: /* Move to forced wait state */ 60: if ( state == TS_READY ) { 61: make_non_ready(tcb); 62: tcb->state = TS_SUSPEND; 63: 64: } else if ( state == TS_WAIT ) { 65: tcb->state = TS_WAITSUS; 66: } 67: 68: error_exit: 69: END_CRITICAL_SECTION; 70: 71: return ercd; 72: } 73: 74: /* 75: * Resume task 76: */ 77: SYSCALL ER _tk_rsm_tsk( ID tskid ) 78: { 79: TCB *tcb; 80: ER ercd = E_OK; 81: 82: CHECK_TSKID(tskid); 83: CHECK_NONSELF(tskid); 84: 85: tcb = get_tcb(tskid); 86: 87: BEGIN_CRITICAL_SECTION; 88: switch ( tcb->state ) { 89: case TS_NONEXIST: 90: ercd = E_NOEXS; 91: break; 92: 93: case TS_DORMANT: 94: case TS_READY: 95: case TS_WAIT: 96: ercd = E_OBJ; 97: break; 98: 99: case TS_SUSPEND: 100: if ( --tcb->suscnt == 0 ) { 101: make_ready(tcb); 102: } 103: break; 104: case TS_WAITSUS: 105: if ( --tcb->suscnt == 0 ) { 106: tcb->state = TS_WAIT; 107: } 108: break; 109: 110: default: 111: ercd = E_SYS; 112: break; 113: } 114: END_CRITICAL_SECTION; 115: 116: return ercd; 117: } 118: 119: /* 120: * Force resume task 121: */ 122: SYSCALL ER _tk_frsm_tsk( ID tskid ) 123: { 124: TCB *tcb; 125: ER ercd = E_OK; 126: 127: CHECK_TSKID(tskid); 128: CHECK_NONSELF(tskid); 129: 130: tcb = get_tcb(tskid); 131: 132: BEGIN_CRITICAL_SECTION; 133: switch ( tcb->state ) { 134: case TS_NONEXIST: 135: ercd = E_NOEXS; 136: break; 137: 138: case TS_DORMANT: 139: case TS_READY: 140: case TS_WAIT: 141: ercd = E_OBJ; 142: break; 143: 144: case TS_SUSPEND: 145: tcb->suscnt = 0; 146: make_ready(tcb); 147: break; 148: case TS_WAITSUS: 149: tcb->suscnt = 0; 150: tcb->state = TS_WAIT; 151: break; 152: 153: default: 154: ercd = E_SYS; 155: break; 156: } 157: END_CRITICAL_SECTION; 158: 159: return ercd; 160: } 161: 162: /* ------------------------------------------------------------------------ */ 163: 164: /* 165: * Definition of task wait specification 166: */ 167: LOCAL CONST WSPEC wspec_slp = { TTW_SLP, NULL, NULL }; 168: 169: /* 170: * Move its own task state to wait state 171: */ 172: SYSCALL ER _tk_slp_tsk( TMO tmout ) 173: { 174: return _tk_slp_tsk_u(to_usec_tmo(tmout)); 175: } 176: 177: SYSCALL ER _tk_slp_tsk_u( TMO_U tmout ) 178: { 179: ER ercd = E_OK; 180: 181: CHECK_TMOUT(tmout); 182: CHECK_DISPATCH(); 183: 184: BEGIN_CRITICAL_SECTION; 185: /* Check wait disable */ 186: if ( (ctxtsk->waitmask & TTW_SLP) != 0 ) { 187: ercd = E_DISWAI; 188: goto error_exit; 189: } 190: 191: if ( ctxtsk->wupcnt > 0 ) { 192: ctxtsk->wupcnt--; 193: } else { 194: ercd = E_TMOUT; 195: if ( tmout != TMO_POL ) { 196: ctxtsk->wspec = &wspec_slp; 197: ctxtsk->wid = 0; 198: ctxtsk->wercd = &ercd; 199: make_wait(tmout, TA_NULL); 200: QueInit(&ctxtsk->tskque); 201: } 202: } 203: 204: error_exit: 205: END_CRITICAL_SECTION; 206: 207: return ercd; 208: } 209: 210: /* 211: * Wakeup task 212: */ 213: SYSCALL ER _tk_wup_tsk( ID tskid ) 214: { 215: TCB *tcb; 216: TSTAT state; 217: ER ercd = E_OK; 218: 219: CHECK_TSKID(tskid); 220: CHECK_NONSELF(tskid); 221: 222: tcb = get_tcb(tskid); 223: 224: BEGIN_CRITICAL_SECTION; 225: state = (TSTAT)tcb->state; 226: if ( !task_alive(state) ) { 227: ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; 228: 229: } else if ( (state & TS_WAIT) != 0 && tcb->wspec == &wspec_slp ) { 230: wait_release_ok(tcb); 231: 232: } else if ( tcb->wupcnt == INT_MAX ) { 233: ercd = E_QOVR; 234: } else { 235: ++tcb->wupcnt; 236: } 237: END_CRITICAL_SECTION; 238: 239: return ercd; 240: } 241: 242: /* 243: * Cancel wakeup request 244: */ 245: SYSCALL INT _tk_can_wup( ID tskid ) 246: { 247: TCB *tcb; 248: ER ercd = E_OK; 249: 250: CHECK_TSKID_SELF(tskid); 251: 252: tcb = get_tcb_self(tskid); 253: 254: BEGIN_CRITICAL_SECTION; 255: switch ( tcb->state ) { 256: case TS_NONEXIST: 257: ercd = E_NOEXS; 258: break; 259: case TS_DORMANT: 260: ercd = E_OBJ; 261: break; 262: 263: default: 264: ercd = tcb->wupcnt; 265: tcb->wupcnt = 0; 266: } 267: END_CRITICAL_SECTION; 268: 269: return ercd; 270: } 271: 272: /* ------------------------------------------------------------------------ */ 273: 274: #define toTTW(evtmask) ( (UINT)(evtmask) << 16 ) 275: #define toEVT(tskwait) ( (UB)((tskwait) >> 16) ) 276: 277: /* 278: * Wait for task event 279: */ 280: SYSCALL INT _tk_wai_tev( INT waiptn, TMO tmout ) 281: { 282: return _tk_wai_tev_u(waiptn, to_usec_tmo(tmout)); 283: } 284: 285: SYSCALL INT _tk_wai_tev_u( INT waiptn, TMO_U tmout ) 286: { 287: WSPEC wspec; 288: ER ercd; 289: 290: CHECK_TMOUT(tmout); 291: CHECK_PAR((((UINT)waiptn & ~0x000000ffU) == 0)&&(((UINT)waiptn & 0x000000FFU) != 0)); 292: CHECK_DISPATCH(); 293: 294: BEGIN_CRITICAL_SECTION; 295: /* Check wait disable */ 296: if ( (ctxtsk->waitmask & toTTW(waiptn)) != 0 ) { 297: ercd = E_DISWAI; 298: goto error_exit; 299: } 300: 301: if ( (ctxtsk->tskevt & waiptn) != 0 ) { 302: ercd = ctxtsk->tskevt; 303: ctxtsk->tskevt &= ~waiptn; 304: } else { 305: ercd = E_TMOUT; 306: if ( tmout != TMO_POL ) { 307: wspec.tskwait = toTTW(waiptn); 308: wspec.chg_pri_hook = NULL; 309: wspec.rel_wai_hook = NULL; 310: ctxtsk->wspec = &wspec; 311: ctxtsk->wid = 0; 312: ctxtsk->wercd = &ercd; 313: make_wait(tmout, TA_NULL); 314: QueInit(&ctxtsk->tskque); 315: } 316: } 317: 318: error_exit: 319: END_CRITICAL_SECTION; 320: 321: return ercd; 322: } 323: 324: /* 325: * Send task event 326: */ 327: SYSCALL ER _tk_sig_tev( ID tskid, INT tskevt ) 328: { 329: UINT evtmsk; 330: TCB *tcb; 331: TSTAT state; 332: ER ercd = E_OK; 333: 334: CHECK_TSKID_SELF(tskid); 335: CHECK_PAR(tskevt >= 1 && tskevt <= 8); 336: 337: evtmsk = (UINT)(1 << (tskevt - 1)); 338: tcb = get_tcb_self(tskid); 339: 340: BEGIN_CRITICAL_SECTION; 341: state = (TSTAT)tcb->state; 342: if ( !task_alive(state) ) { 343: ercd = ( state == TS_NONEXIST )? E_NOEXS: E_OBJ; 344: goto error_exit; 345: } 346: 347: if ( (state & TS_WAIT) != 0 && (tcb->wspec->tskwait & toTTW(evtmsk)) != 0 ) { 348: wait_release_ok_ercd(tcb, (ER)(tcb->tskevt | evtmsk)); 349: } else { 350: tcb->tskevt |= evtmsk; 351: } 352: 353: error_exit: 354: END_CRITICAL_SECTION; 355: 356: return ercd; 357: }