sync.c
1 /************************************************************************** 2 BuguRTOS-4.0.x (Bugurt real time operating system) 3 Copyright (C) 2018 anonimous 4 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 Please contact with me by E-mail: shkolnick.kun@gmail.com 19 20 A special exception to the GPL can be applied should you wish to distribute 21 a combined work that includes BuguRTOS, without being obliged to provide 22 the source code for any proprietary components. See the file exception.txt 23 for full details of how and when the exception can be applied. 24 **************************************************************************/ 25 26 /***************************************************************************************** 27 ```````````````````````````````..:+oyhdmNNMMMMMMNmmdhyo+:..``````````````````````````````` 28 ``````````````````````````.:oydNMMMMMMMMMNNNNNNNNMMMMMMMMMNdy+:.`````````````````````````` 29 ```````````````````````:sdNMMMMMNdys+/::----------::/osydNMMMMMNds:``````````````````````` 30 ```````````````````.+hNMMMMmho/-..........................-/shmMMMMNh/.``````````````````` 31 ````````````````./hNMMMNho:...................................-:ohNMMMNh/````````````````` 32 ``````````````.smMMMNy/-.......:////ss++/+-.......................-+yNMMMmo.`````````````` 33 ````````````-sNMMMd+-.....:////:-...-/s::..............+o/-..........-odMMMNs.```````````` 34 ``````````.sNMMNh/....................................-o:--............./hMMMNo.`````````` 35 `````````+mMMMh:-........................................-...............-/dMMMm/````````` 36 ```````.yMMMm/...................-::--..................:-........--........+mMMMy.``````` 37 ``````:mMMMy-.......................-::-...............-:.........-::........-yMMMd:`````` 38 `````/NMMN+-..................::-.....-:-............../--.........-:/-.......-+NMMN:````` 39 ````+NMMm::o/-..--/+o+o+++++o+osys+//::-::.............:/....-:-::-..-++-.......:NMMN/```` 40 ```/NMMm:.-++-+yhs/-`` `dMMMMMmho+:-..............:-/+yho/:/+oyo//o-......./mMMN:``` 41 ``-NMMm/....-/--::/o+o+oo+oo++oosyss+smyo/.............:yyho-` smMMddh-......./NMMN.`` 42 `.hMMM/......-++:-.-:oooooooooosyyhhys/...............-+osyyyyysssssooo+ohhs-......+MMMh.` 43 `+MMMy.......-::/++:-.....-:/++++o+o/--................--/oooo+o++o+++////-y/.......hMMM/` 44 .mMMN:.........--:---...-::/+//::--.......................--//+//-...-.....+/......./NMMd` 45 /MMMy............-::----------....----/+-.....................-++/:---....-o-........hMMN: 46 yMMM/.............--:://///oo+++/+++oo+-.......................-://+/:--::::.........+MMMs 47 mMMN:................----:/h:::/:/::---.........................--/osss+++:..........:NMMd 48 MMMd-....................:mNs:-....................................--:odo:-..........:mMMN 49 MMMd-....................yoshyoso:--................................../mm/...........:mMMM 50 MMMm:..................../-o/h.y-:+dooo+/:--....................-/osydddmh...........:mMMN 51 mMMN:........................+mNs `h. -d/:/+h++ooooy+++s++y+++mo+y` yh.do...........:NMMh 52 sMMM+........................-hmMo/ds oMo`.-o :h s:`h` `Nysd.-Ny-h:...........+MMMo 53 /MMMh........................./smMMMMd+NMMNNMh` sN: .mNNMddNMMMMNmN+..............hMMN: 54 .dMMN/........................./+hMMMMMMMMMMMMmhyyyNMNNMMMMMMMMMMMNsoo-............./NMMd` 55 `+MMMh.........................-/+omMMMMMMMMMMMMMMMMMMMMMMMMMMMMms-/+...............hMMM/` 56 `.hMMM+..........................:/-omMMMMMMMMMMMMMMMdmMdhMMMds/-..-...............oMMMy`` 57 ``.NMMN/............................--/hNN/h.`ys:dmsd:-syos+--+.................../NMMN.`` 58 ```/NMMm:...........................:+/--:+s++oo+osoo+/:-..-/+::-................/mMMN:``` 59 ````/NMMN:............................-/++/:-..........-//+/-..:+.--............/NMMN/```` 60 `````:NMMN+-.............../+-.............-://////////:-.......+s+::.........-oNMMN:````` 61 ``````:mMMMy-..............:/o-.................................:yo//........-hMMMd-`````` 62 ```````.yMMMm+.............:o:++-...............................+y+o-......-+mMMMs.``````` 63 `````````/mMMMd/-...........-++:+/-.---........................-ho+/.....-/dMMMm/````````` 64 ``````````.oNMMMh/............-++:++/////:....................-yo:o-...-+hMMMNo.`````````` 65 ````````````.sNMMMdo-...........-++::++:-:/+//:..............:o:/o-..-omMMMNo.```````````` 66 ``````````````.omMMMNy+-..........-/+-.:/+/:--:+++/++//:/::/+/-+/.-+hMMMMmo``````````````` 67 `````````````````/hNMMMNho:-...............-:/:-....--::::--..-/ohNMMMNy:````````````````` 68 ```````````````````./hNMMMMmhs/-..........................-/shNMMMMNy/.``````````````````` 69 ```````````````````````:sdNMMMMMNdhso+/:----------:/+oshdNMMMMMNho:``````````````````````` 70 ``````````````````````````.:+ydNMMMMMMMMMMNNNNNNMMMMMMMMMMmds+:``````````````````````````` 71 ````````````````````````````````.:/osyhdmNNMMMMNNmdhyso/:.```````````````````````````````` 72 ****************************************************************************************** 73 * * 74 * This logo was graciously delivered by 10003-kun ITT: * 75 * * 76 * http://www.0chan.ru/r/res/9996.html * 77 * * 78 *****************************************************************************************/ 79 #include "bugurt.h" 80 /* ADLINT:SF:[W9001,W0431,W0432,W0422] control never...WTF??!, 2x(indentation in switches), NULL ptr*/ 81 /*Run a process with higher prio to avoid prio inversion!*/ 82 static void _pctrl_proc_run_high(bgrt_proc_t * proc, bgrt_flag_t state) 83 { 84 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 85 86 BGRT_PROC_LRES_INC(proc, 0); 87 ((bgrt_pitem_t *)proc)->prio = (bgrt_prio_t)0; 88 bgrt_sched_proc_run(proc, state); 89 } 90 /*====================================================================================*/ 91 /*Change a process priority according to its #lres data field.*/ 92 static void _pctrl_proc_stoped(bgrt_proc_t * proc) 93 { 94 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 95 96 if ((bgrt_map_t)0 != proc->lres.map) 97 { 98 99 bgrt_prio_t locker_prio; 100 locker_prio = bgrt_map_search(proc->lres.map); 101 ((bgrt_pitem_t *)proc)->prio = (locker_prio < proc->base_prio)?locker_prio:proc->base_prio; 102 } 103 else 104 { 105 ((bgrt_pitem_t *)proc)->prio = proc->base_prio; 106 } 107 } 108 /*====================================================================================*/ 109 static void _pctrl_proc_run(bgrt_proc_t * proc, bgrt_flag_t state) 110 { 111 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 112 113 _pctrl_proc_stoped(proc); 114 bgrt_sched_proc_run(proc, state); 115 } 116 /*====================================================================================*/ 117 static void _pctrl_proc_running(bgrt_proc_t * proc, bgrt_flag_t state) 118 { 119 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 120 121 bgrt_priv_proc_stop_ensure(proc, BGRT_PROC_STATE_STOPED); 122 _pctrl_proc_run(proc, state); 123 } 124 /*====================================================================================*/ 125 bgrt_prio_t bgrt_priv_sync_prio(bgrt_sync_t * sync) 126 { 127 bgrt_prio_t sprio; /*sync prio*/ 128 129 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 130 131 sprio = sync->prio; 132 if ((((bgrt_xlist_t *)sync)->map)) 133 { 134 bgrt_prio_t wprio; /*wait list prio*/ 135 136 wprio = bgrt_map_search(((bgrt_xlist_t *)sync)->map); 137 return (wprio < sprio)?wprio:sprio; /* ADLINT:SL:[W0256,W0268] signed/unsigned*/ 138 } 139 else 140 { 141 return sprio; /* ADLINT:SL:[W0256,W0268] signed/unsigned*/ 142 } 143 } 144 /*====================================================================================*/ 145 static void _sync_do_wake(bgrt_proc_t * proc, bgrt_sync_t * sync, bgrt_flag_t chown) 146 { 147 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 148 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 149 150 BGRT_SPIN_LOCK(proc); 151 152 /*It doesn't wait on sync any more.*/ 153 proc->sync = (void *)0; /* ADLINT:SL:[W0567] type conversion*/ 154 155 if (BGRT_PROC_STATE_PI_PEND == BGRT_PROC_GET_STATE(proc)) 156 { 157 BGRT_PROC_SET_STATE (proc, BGRT_PROC_STATE_PI_DONE); /* ADLINT:SL:[W0447] coma operator*/ 158 if (chown) 159 { 160 BGRT_PROC_LRES_INC(proc, BGRT_SYNC_PRIO(sync)); 161 } 162 } 163 else 164 { 165 bgrt_pitem_cut((bgrt_pitem_t *)proc); 166 if (chown) 167 { 168 BGRT_PROC_LRES_INC(proc, BGRT_SYNC_PRIO(sync)); 169 _pctrl_proc_stoped(proc); 170 } 171 _pctrl_proc_run_high(proc, BGRT_PROC_STATE_SYNC_READY); 172 } 173 BGRT_SPIN_FREE(proc); 174 } 175 /*====================================================================================*/ 176 static void _sync_do_pending_wake(bgrt_sync_t * sync) 177 { 178 bgrt_proc_t * proc; 179 180 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 181 182 proc = (bgrt_proc_t *)bgrt_xlist_head((bgrt_xlist_t *)sync); 183 if (proc) 184 { 185 sync->pwake--; 186 _sync_do_wake(proc, sync, (bgrt_flag_t)0); 187 } 188 else 189 { 190 return;/** Not covered!!! How about panic here???*/ 191 } 192 } 193 /*====================================================================================*/ 194 #ifdef BGRT_CONFIG_MP 195 # define BGRT_PCTRL_PROP_ARGS bgrt_proc_t * proc, bgrt_code_t hook, void * hook_arg /* ADLINT:SL:[W0479] typedef?? Hell NO!*/ 196 # define BGRT_PCTRL_PROP_HOOK() hook(hook_arg) 197 # define BGRT_PCTRL_PROP_HOOK_ASSERT() BGRT_ASSERT(hook, "The #hook must not be NULL!") 198 # define BGRT_PCTRL_PROP_HOOKARG_ASSERT() BGRT_ASSERT(hook_arg, "The #hook_arg must not be NULL!") 199 #else /*BGRT_CONFIG_MP*/ 200 # define BGRT_PCTRL_PROP_ARGS bgrt_proc_t * proc 201 # define BGRT_PCTRL_PROP_HOOK() do{}while (0) 202 # define BGRT_PCTRL_PROP_HOOK_ASSERT() do{}while (0) 203 # define BGRT_PCTRL_PROP_HOOKARG_ASSERT() do{}while (0) 204 #endif /*BGRT_CONFIG_MP*/ 205 static void _pctrl_propagate(BGRT_PCTRL_PROP_ARGS) 206 { 207 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 208 BGRT_PCTRL_PROP_HOOK_ASSERT(); 209 BGRT_PCTRL_PROP_HOOKARG_ASSERT(); 210 211 switch(BGRT_PROC_GET_STATE(proc)) 212 { 213 case BGRT_PROC_STATE_READY: 214 case BGRT_PROC_STATE_RUNNING: 215 case BGRT_PROC_STATE_TO_READY: 216 case BGRT_PROC_STATE_TO_RUNNING: 217 case BGRT_PROC_STATE_SYNC_READY: 218 case BGRT_PROC_STATE_SYNC_RUNNING: 219 case BGRT_PROC_STATE_PI_READY: 220 case BGRT_PROC_STATE_PI_RUNNING: 221 { 222 bgrt_flag_t state; 223 state = BGRT_PROC_GET_STATE(proc); 224 _pctrl_proc_running(proc, state); 225 BGRT_PCTRL_PROP_HOOK(); 226 break; 227 } 228 case BGRT_PROC_STATE_SYNC_SLEEP: /* ADLINT:SL:[W0007] return/break */ 229 { 230 bgrt_sync_t * sync; 231 bgrt_prio_t old_prio, new_prio; 232 /* Ensure that process will not run, and stay in a sync sleep list!*/ 233 BGRT_PROC_SET_STATE(proc, BGRT_PROC_STATE_PI_PEND); /* ADLINT:SL:[W0447] coma operator*/ 234 235 sync = proc->sync; 236 237 BGRT_PCTRL_PROP_HOOK(); 238 239 BGRT_KERNEL_PREEMPT(); /* ADLINT:SL:[W0705,W0067] OOR access*/ 240 241 if ((bgrt_sync_t *)0 == sync) /* ADLINT:SL:[W0567] type conversion*/ 242 { 243 /* A process was trying to free a dirty sync and blocked */ 244 BGRT_SPIN_LOCK(proc); 245 246 _pctrl_proc_run(proc, BGRT_PROC_STATE_READY); /* A process must unlock the sync. */ 247 248 BGRT_SPIN_FREE(proc); 249 break; /*Break the switch!*/ 250 } 251 252 BGRT_SPIN_LOCK(sync); 253 254 old_prio = BGRT_SYNC_PRIO(sync); /* Get sync prio to keep sync->owner priority data consistent*/ 255 256 BGRT_SPIN_LOCK(proc); 257 258 bgrt_pitem_cut((bgrt_pitem_t *)proc); 259 if (BGRT_PROC_STATE_PI_PEND == BGRT_PROC_GET_STATE(proc)) 260 { 261 if (sync->owner) 262 { 263 /*Start priority inheritance transaction.*/ 264 BGRT_CNT_INC(sync->dirty); 265 /*To avoid prio inversion!!!*/ 266 _pctrl_proc_run_high(proc, BGRT_PROC_STATE_PI_READY); 267 } 268 else 269 { 270 /*Put back into sync->sleep*/ 271 _pctrl_proc_stoped(proc); 272 BGRT_PROC_SET_STATE(proc, BGRT_PROC_STATE_SYNC_SLEEP); /* ADLINT:SL:[W0447] coma operator*/ 273 bgrt_pitem_insert((bgrt_pitem_t *)proc, (bgrt_xlist_t *)sync); 274 } 275 } 276 else 277 { 278 /*Finish process wakeup*/ 279 _pctrl_proc_run_high(proc, BGRT_PROC_STATE_SYNC_READY); 280 } 281 282 BGRT_SPIN_FREE(proc); 283 284 proc = sync->owner; 285 if (proc) 286 { 287 /*Keep priority data consistent*/ 288 new_prio = BGRT_SYNC_PRIO(sync); 289 if (new_prio != old_prio) 290 { 291 BGRT_SPIN_LOCK(proc); 292 BGRT_PROC_LRES_DEC(proc, old_prio); /* ADLINT:SL:[W1073] retval discarded*/ 293 BGRT_PROC_LRES_INC(proc, new_prio); 294 BGRT_SPIN_FREE(proc); 295 } 296 } 297 BGRT_SPIN_FREE(sync); 298 break; 299 } 300 case BGRT_PROC_STATE_SYNC_WAIT: /* ADLINT:SL:[W0007] return/break */ 301 { 302 _pctrl_proc_run(proc, BGRT_PROC_STATE_READY); 303 BGRT_PCTRL_PROP_HOOK(); 304 break; 305 } 306 case BGRT_PROC_STATE_STOPED: /* ADLINT:SL:[W0007] return/break */ 307 case BGRT_PROC_STATE_END: /* ADLINT:SL:[W0007] return/break */ 308 case BGRT_PROC_STATE_WD_STOPED: /* ADLINT:SL:[W0007] return/break */ 309 case BGRT_PROC_STATE_DEAD: /* ADLINT:SL:[W0007] return/break */ 310 { 311 _pctrl_proc_stoped(proc); 312 } 313 case BGRT_PROC_STATE_PI_PEND: /* ADLINT:SL:[W0007] return/break */ 314 case BGRT_PROC_STATE_PI_DONE: /* ADLINT:SL:[W0007] return/break */ 315 default: 316 { 317 BGRT_PCTRL_PROP_HOOK(); 318 } 319 } 320 } 321 /*====================================================================================*/ 322 #ifdef BGRT_CONFIG_MP 323 # define BGRT_PROC_PS_PI_PRIO_PROPAGATE(p) _pctrl_propagate(p, (bgrt_code_t)bgrt_spin_free, (void *)&p->lock) 324 #else /*BGRT_CONFIG_MP*/ 325 # define BGRT_PROC_PS_PI_PRIO_PROPAGATE(p) _pctrl_propagate(p) 326 #endif /*BGRT_CONFIG_MP*/ 327 void bgrt_priv_proc_set_prio(bgrt_proc_t * proc, bgrt_prio_t prio) 328 { 329 if (!proc) 330 { 331 proc = bgrt_curr_proc(); 332 } 333 BGRT_SPIN_LOCK(proc); 334 proc->base_prio = prio; 335 BGRT_PROC_PS_PI_PRIO_PROPAGATE(proc); /* ADLINT:SL:[W0553,W0021] function type conversion, volatile discarded*/ 336 } 337 /********************************************************************************************** 338 Bsync methods 339 **********************************************************************************************/ 340 #ifdef BGRT_CONFIG_MP 341 static void _sync_prio_prop_hook(bgrt_sync_t * sync) 342 { 343 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 344 BGRT_ASSERT(sync->owner, "The #sync->owner must not be NULL!"); 345 346 BGRT_SPIN_FREE((sync->owner)); 347 BGRT_SPIN_FREE(sync); 348 } 349 # define BGRT_SYNC_PI_PRIO_PROPAGATE(p,m) _pctrl_propagate(p, (bgrt_code_t)_sync_prio_prop_hook, (void *)m) 350 #else /*BGRT_CONFIG_MP*/ 351 # define BGRT_SYNC_PI_PRIO_PROPAGATE(p,m) _pctrl_propagate(p) 352 #endif /*BGRT_CONFIG_MP*/ 353 /*====================================================================================*/ 354 bgrt_st_t bgrt_sync_init(bgrt_sync_t * sync, bgrt_prio_t prio) 355 { 356 bgrt_st_t ret; 357 358 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 359 360 BGRT_INT_LOCK(); 361 ret = bgrt_priv_sync_init(sync, prio); 362 BGRT_INT_FREE(); 363 return ret; 364 } 365 /*====================================================================================*/ 366 bgrt_st_t bgrt_priv_sync_init(bgrt_sync_t * sync, bgrt_prio_t prio) 367 { 368 if (!sync) 369 { 370 return BGRT_ST_ENULL; 371 } 372 373 BGRT_SPIN_INIT(sync); 374 BGRT_SPIN_LOCK(sync); 375 bgrt_xlist_init((bgrt_xlist_t *)sync); 376 sync->owner = (bgrt_proc_t *)0; /* ADLINT:SL:[W0567] int to pinter*/ 377 sync->dirty = (bgrt_cnt_t)0; 378 sync->snum = (bgrt_cnt_t)0; 379 sync->pwake = (bgrt_cnt_t)0; 380 sync->prio = prio; 381 BGRT_SPIN_FREE(sync); 382 return BGRT_ST_OK; 383 } 384 /*====================================================================================*/ 385 bgrt_proc_t * bgrt_priv_sync_get_owner(bgrt_sync_t * sync) 386 { 387 bgrt_proc_t * ret; 388 389 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 390 391 BGRT_SPIN_LOCK(sync); 392 ret = sync->owner; 393 BGRT_SPIN_FREE(sync); 394 return ret; 395 } 396 /*====================================================================================*/ 397 static void _sync_assign_owner(bgrt_sync_t * sync, bgrt_proc_t * proc) 398 { 399 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 400 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 401 402 sync->owner = proc; 403 BGRT_SPIN_LOCK(proc); 404 BGRT_PROC_LRES_INC(proc, BGRT_SYNC_PRIO(sync)); 405 BGRT_SYNC_PI_PRIO_PROPAGATE(proc, sync); /* ADLINT:SL:[W0553] function type conversion */ 406 } 407 /*====================================================================================*/ 408 bgrt_st_t bgrt_priv_sync_set_owner(bgrt_sync_t * sync, bgrt_proc_t * proc) 409 { 410 bgrt_proc_t * owner; 411 bgrt_prio_t old_prio; 412 413 if (!sync) 414 { 415 return BGRT_ST_ENULL; 416 } 417 418 /*Clear last owner*/ 419 BGRT_SPIN_LOCK(sync); 420 421 old_prio = BGRT_SYNC_PRIO(sync); 422 owner = sync->owner; 423 424 if (owner == proc) 425 { 426 BGRT_SPIN_FREE(sync); 427 428 return BGRT_ST_OK; 429 } 430 431 sync->owner = (bgrt_proc_t *)0; /* ADLINT:SL:[W0567] integer to pointer*/ 432 BGRT_SPIN_FREE(sync); 433 434 /*check proc*/ 435 if (owner) 436 { 437 /*update proc priority info*/ 438 BGRT_SPIN_LOCK(owner); 439 BGRT_PROC_LRES_DEC(owner, old_prio); /* ADLINT:SL:[W1073] retval discarded*/ 440 BGRT_PROC_PS_PI_PRIO_PROPAGATE(owner); /* ADLINT:SL:[W0553,W0021] function type conversion, volatile discarded*/ 441 } 442 443 /*Check new owner*/ 444 if (!proc) 445 { 446 return BGRT_ST_OK; 447 } 448 449 /*We have some new owner*/ 450 BGRT_SPIN_LOCK(sync); 451 _sync_assign_owner(sync, proc); 452 453 return BGRT_ST_OK; 454 } 455 /*====================================================================================*/ 456 static void _sync_touch_prio_up(bgrt_sync_t * sync, bgrt_proc_t * proc) 457 { 458 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 459 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 460 461 BGRT_SPIN_LOCK(proc); 462 463 bgrt_priv_proc_stop_ensure(proc, BGRT_PROC_STATE_STOPED); 464 proc->sync = sync; 465 _pctrl_proc_run_high(proc, BGRT_PROC_STATE_RUNNING); 466 467 BGRT_SPIN_FREE(proc); 468 } 469 470 /*====================================================================================*/ 471 bgrt_st_t bgrt_priv_sync_own(bgrt_sync_t * sync, bgrt_flag_t touch) 472 { 473 bgrt_proc_t * owner; 474 475 if (!sync) 476 { 477 return BGRT_ST_ENULL; 478 } 479 BGRT_SPIN_LOCK(sync); 480 481 owner = sync->owner; 482 if (!owner) 483 { 484 _sync_assign_owner(sync, bgrt_curr_proc()); 485 486 return BGRT_ST_OK; 487 } 488 else 489 { 490 bgrt_proc_t * current; 491 current = bgrt_curr_proc(); 492 493 if (touch && (owner != current)) 494 { 495 BGRT_CNT_INC(sync->dirty); 496 BGRT_CNT_INC(sync->snum); /*Increment sleeping process counter. Caller is going to sleep.*/ 497 BGRT_SPIN_FREE(sync); 498 499 _sync_touch_prio_up(sync, current); 500 } 501 else 502 { 503 BGRT_SPIN_FREE(sync); 504 } 505 return BGRT_ST_EOWN; 506 } 507 } 508 /*====================================================================================*/ 509 bgrt_st_t bgrt_priv_sync_touch(bgrt_sync_t * sync) 510 { 511 bgrt_proc_t * current; 512 513 if (!sync) 514 { 515 return BGRT_ST_ENULL; 516 } 517 518 BGRT_SPIN_LOCK(sync); 519 BGRT_CNT_INC(sync->dirty); 520 BGRT_CNT_INC(sync->snum); /*Increment sleeping process counter. Caller is going to sleep.*/ 521 BGRT_SPIN_FREE(sync); 522 523 current = bgrt_curr_proc(); 524 _sync_touch_prio_up(sync, current); 525 526 return BGRT_ST_OK; 527 } 528 /*====================================================================================*/ 529 #ifdef BGRT_CONFIG_MP 530 static inline void _sync_sleep_swap_locks(bgrt_sync_t * sync, bgrt_proc_t * proc) 531 { 532 BGRT_ASSERT(sync, "The #sync must not be NULL!"); 533 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 534 535 BGRT_SPIN_FREE(proc); 536 BGRT_KERNEL_PREEMPT(); /* ADLINT:SL:[W0705,W0067] OOR access*/ 537 BGRT_SPIN_LOCK(sync); 538 BGRT_SPIN_LOCK(proc); 539 } 540 # define _SYNC_SLEEP_SWAP_LOCKS _sync_sleep_swap_locks 541 #else/*BGRT_CONFIG_MP*/ 542 # define _SYNC_SLEEP_SWAP_LOCKS(sync, proc) do{}while(0) 543 #endif/*BGRT_CONFIG_MP*/ 544 /*====================================================================================*/ 545 bgrt_st_t bgrt_priv_sync_sleep(bgrt_sync_t * sync, bgrt_flag_t * touch) 546 { 547 bgrt_proc_t * proc; 548 bgrt_prio_t old_prio; 549 bgrt_prio_t new_prio; 550 bgrt_flag_t sync_clear; /*Used as event flag and as temp var;*/ 551 552 bgrt_priv_proc_reset_watchdog(); 553 554 if (!sync) 555 { 556 return BGRT_ST_ENULL; 557 } 558 559 proc = bgrt_curr_proc(); 560 561 BGRT_SPIN_LOCK(proc); 562 /*Use sync_clear as temp var.*/ 563 if (touch) 564 { 565 if (*touch) 566 { 567 /*Clear flag*/ 568 *touch = 0; /* ADLINT:SL:[W0167] OOR access*/ 569 sync_clear = BGRT_PROC_STATE_PI_RUNNING; 570 } 571 else 572 { 573 sync_clear = BGRT_PROC_GET_STATE(proc); /* ADLINT:SL:[W0447] coma operator*/ 574 } 575 } 576 else 577 { 578 sync_clear = BGRT_PROC_GET_STATE(proc); /* ADLINT:SL:[W0447] coma operator*/ 579 } 580 BGRT_PROC_SET_STATE(proc, BGRT_PROC_STATE_RUNNING); /* ADLINT:SL:[W0447] coma operator*/ 581 582 switch(sync_clear) 583 { 584 case BGRT_PROC_STATE_SYNC_RUNNING: 585 { 586 BGRT_PROC_LRES_DEC(proc, 0); /* ADLINT:SL:[W1073] retval discarded*/ 587 _pctrl_proc_running(proc, BGRT_PROC_STATE_RUNNING); 588 589 BGRT_SPIN_FREE(proc); 590 BGRT_KERNEL_PREEMPT(); /* ADLINT:SL:[W0705,W0067] OOR access*/ 591 BGRT_SPIN_LOCK(sync); 592 593 BGRT_CNT_DEC(sync->snum); /*One sleeping proc less!*/ 594 595 if (sync->pwake) 596 { 597 _sync_do_pending_wake(sync); 598 } 599 BGRT_SPIN_FREE(sync); 600 601 return BGRT_ST_OK; 602 } 603 case BGRT_PROC_STATE_TO_RUNNING: /* ADLINT:SL:[W0007] return/break */ 604 { 605 /*sync->snum decremented in bgrt_priv_sync_proc_timeout !!!*/ 606 /*no need to BGRT_SPIN_LOCK(sync)!!!*/ 607 BGRT_SPIN_FREE(proc); 608 609 return BGRT_ST_ETIMEOUT; 610 } 611 case BGRT_PROC_STATE_PI_RUNNING: /* ADLINT:SL:[W0007] return/break */ 612 { 613 /*The end of priority inheritance transaction or BGRT_SYNC_OWN transaction*/ 614 _SYNC_SLEEP_SWAP_LOCKS(sync, proc); 615 /*Event!*/ 616 sync_clear = (bgrt_flag_t)((bgrt_cnt_t)1 == sync->dirty); /* ADLINT:SL:[W0608] minus converted*/ 617 BGRT_CNT_DEC(sync->dirty); 618 619 bgrt_priv_proc_stop_ensure(proc, BGRT_PROC_STATE_SYNC_SLEEP); 620 621 BGRT_PROC_LRES_DEC(proc, 0); /* ADLINT:SL:[W1073] retval discarded*/ 622 _pctrl_proc_stoped(proc); 623 624 if (sync->owner == proc) 625 { 626 bgrt_sched_proc_run(proc, BGRT_PROC_STATE_READY); 627 628 BGRT_SPIN_FREE(proc); 629 630 BGRT_CNT_DEC(sync->snum); /*The process become an owner during a prio inheritance transaction!*/ 631 BGRT_SPIN_FREE(sync); 632 633 return BGRT_ST_EOWN; 634 } 635 else 636 { 637 break; 638 } 639 } 640 case BGRT_PROC_STATE_RUNNING: /* ADLINT:SL:[W0007] return/break */ 641 default: 642 { 643 _SYNC_SLEEP_SWAP_LOCKS(sync, proc); 644 if (sync->owner == proc) 645 { 646 BGRT_SPIN_FREE(proc); 647 BGRT_SPIN_FREE(sync); 648 649 return BGRT_ST_EOWN; 650 } 651 else 652 { 653 bgrt_priv_proc_stop_ensure(proc, BGRT_PROC_STATE_SYNC_SLEEP); 654 BGRT_CNT_INC(sync->snum); /*Increment sleeping process counter. Caller is going to sleep.*/ 655 sync_clear = (bgrt_flag_t)0; /*No event!*/ 656 break; 657 } 658 } 659 } 660 661 old_prio = BGRT_SYNC_PRIO(sync); 662 proc->sync = sync; 663 /*Insert to wait list*/ 664 bgrt_pitem_insert((bgrt_pitem_t *)proc, (bgrt_xlist_t *)sync); 665 666 BGRT_SPIN_FREE(proc); 667 /*Here we process a state, not sync_clear event!*/ 668 if (((bgrt_cnt_t)0 == sync->dirty) && (sync->pwake)) 669 { 670 _sync_do_pending_wake(sync); 671 } 672 673 proc = sync->owner; 674 if (proc) 675 { 676 new_prio = BGRT_SYNC_PRIO(sync); 677 if ((old_prio != new_prio) || sync_clear) 678 { 679 /*When owner in BGRT_PROC_STATE_SYNC_WAIT state, then old_prio != new_prio as sync->sleep was empty when owner called BGRT_SYNC_WAIT.*/ 680 BGRT_SPIN_LOCK(proc); 681 BGRT_PROC_LRES_DEC(proc, old_prio); 682 BGRT_PROC_LRES_INC(proc, new_prio); 683 BGRT_SYNC_PI_PRIO_PROPAGATE(proc, sync); 684 } 685 else 686 { 687 BGRT_SPIN_LOCK(proc); 688 if (BGRT_PROC_STATE_SYNC_WAIT == BGRT_PROC_GET_STATE(proc)) 689 { 690 bgrt_sched_proc_run(proc, BGRT_PROC_STATE_READY); 691 } 692 BGRT_SPIN_FREE(proc); 693 BGRT_SPIN_FREE(sync); 694 } 695 } 696 else 697 { 698 BGRT_SPIN_FREE(sync); 699 } 700 return BGRT_ST_ROLL; 701 } 702 /*====================================================================================*/ 703 static void _sync_owner_block(bgrt_proc_t * owner) 704 { 705 BGRT_ASSERT(owner, "The #owner must not be NULL!"); 706 707 BGRT_SPIN_LOCK(owner); 708 709 owner->sync = (bgrt_sync_t *)0; /* ADLINT:SL:[W0567] int to pinter*/ 710 bgrt_priv_proc_stop_ensure(owner, BGRT_PROC_STATE_SYNC_SLEEP); 711 712 BGRT_SPIN_FREE(owner); 713 } 714 /*====================================================================================*/ 715 bgrt_st_t bgrt_priv_sync_wait(bgrt_sync_t * sync, bgrt_proc_t ** proc, bgrt_flag_t block) 716 { 717 bgrt_proc_t * current; 718 bgrt_proc_t * owner; 719 bgrt_st_t status; 720 721 BGRT_ASSERT(proc, "The #proc must not be NULL!"); 722 723 bgrt_priv_proc_reset_watchdog(); 724 725 if (!sync) 726 { 727 return BGRT_ST_ENULL; 728 } 729 730 current = bgrt_curr_proc(); 731 732 BGRT_SPIN_LOCK(current); 733 if (BGRT_PROC_STATE_TO_RUNNING == BGRT_PROC_GET_STATE(current)) 734 { 735 BGRT_PROC_SET_STATE(current, BGRT_PROC_STATE_RUNNING); /* ADLINT:SL:[W0447] coma operator*/ 736 BGRT_SPIN_FREE(current); 737 738 return BGRT_ST_ETIMEOUT; 739 } 740 else 741 { 742 BGRT_SPIN_FREE(current); 743 } 744 745 BGRT_SPIN_LOCK(sync); 746 owner = sync->owner; 747 748 if (owner != current) 749 { 750 BGRT_SPIN_FREE(sync); 751 return BGRT_ST_EOWN; 752 } 753 754 if (sync->dirty) 755 { 756 _sync_owner_block(owner); 757 BGRT_SPIN_FREE(sync); 758 return BGRT_ST_ROLL; 759 } 760 761 if (!*proc) 762 { 763 *proc = (bgrt_proc_t *)bgrt_xlist_head(((bgrt_xlist_t *)sync)); 764 } 765 766 status = (block)?BGRT_ST_ROLL:BGRT_ST_EEMPTY; 767 if (*proc) 768 { 769 BGRT_SPIN_LOCK((*proc)); 770 if ((*proc)->sync == sync) 771 { 772 status = BGRT_ST_OK; 773 } 774 BGRT_SPIN_FREE((*proc)); 775 }/*else BGRT_ST_ROLL/BGRT_ST_EEMPTY*/ 776 777 if (status == BGRT_ST_ROLL) 778 { 779 BGRT_SPIN_LOCK(owner); 780 bgrt_priv_proc_stop_ensure(owner, BGRT_PROC_STATE_SYNC_WAIT); 781 BGRT_SPIN_FREE(owner); 782 } 783 784 BGRT_SPIN_FREE(sync); 785 return status; 786 } 787 /*====================================================================================*/ 788 bgrt_st_t bgrt_priv_sync_wake(bgrt_sync_t * sync, bgrt_proc_t * proc, bgrt_flag_t chown) 789 { 790 bgrt_proc_t * owner; 791 bgrt_st_t status; 792 793 bgrt_priv_proc_reset_watchdog(); 794 795 if (!sync) 796 { 797 return BGRT_ST_ENULL; 798 } 799 800 BGRT_SPIN_LOCK(sync); 801 owner = sync->owner; 802 /*Check sync ownership*/ 803 if (owner) 804 { 805 if (bgrt_curr_proc() != owner) 806 { 807 BGRT_SPIN_FREE(sync); 808 809 return BGRT_ST_EOWN; 810 } 811 /*Check for dirty priority inheritance transactions*/ 812 if (sync->dirty) 813 { 814 _sync_owner_block(owner); 815 BGRT_SPIN_FREE(sync); 816 817 return BGRT_ST_ROLL; 818 } 819 } 820 else 821 { 822 if (proc) 823 { 824 /*We can,t wake the specified process, as sync is not owned.*/ 825 BGRT_SPIN_FREE(sync); 826 827 return BGRT_ST_EOWN; 828 } 829 830 if (sync->dirty) 831 { 832 if (sync->pwake < sync->snum) 833 { 834 sync->pwake++; 835 status = BGRT_ST_OK; 836 } 837 else 838 { 839 status = BGRT_ST_EEMPTY; /*We can,t wake more processes.*/ 840 } 841 BGRT_SPIN_FREE(sync); 842 843 return status; 844 } 845 } 846 /*Nonzero proc argument???*/ 847 if (proc) /* ADLINT:SL:[W0613] always false??? WTF??!*/ 848 { 849 /*Check proc*/ 850 BGRT_SPIN_LOCK(proc); 851 if (proc->sync != sync) 852 { 853 BGRT_SPIN_FREE(proc); 854 BGRT_SPIN_FREE(sync); 855 856 return BGRT_ST_ESYNC; 857 } 858 BGRT_SPIN_FREE(proc); 859 } 860 else 861 { 862 proc = (bgrt_proc_t *)bgrt_xlist_head((bgrt_xlist_t *)sync); 863 } 864 /*Will now handle sync->owner*/ 865 if (owner) 866 { 867 BGRT_SPIN_LOCK(owner); 868 869 bgrt_sched_proc_stop(owner, BGRT_PROC_STATE_STOPED); 870 BGRT_PROC_LRES_DEC(owner, BGRT_SYNC_PRIO(sync)); /* ADLINT:SL:[W1073] retval discarded*/ 871 /*No prio control now!*/ 872 BGRT_SPIN_FREE(owner); 873 } 874 /*Ownership has been changed.*/ 875 if (chown) 876 { 877 sync->owner = proc; 878 } 879 /*We can wake some proc.*/ 880 if (proc) 881 { 882 _sync_do_wake(proc, sync, chown); 883 status = BGRT_ST_OK; 884 } 885 else 886 { 887 status = BGRT_ST_EEMPTY; 888 } 889 890 if (owner) 891 { 892 BGRT_SPIN_LOCK(owner); 893 894 if (!chown) 895 { 896 BGRT_PROC_LRES_INC(owner, BGRT_SYNC_PRIO(sync)); 897 } 898 _pctrl_proc_run(owner, BGRT_PROC_STATE_READY); 899 900 BGRT_SPIN_FREE(owner); 901 } 902 903 BGRT_SPIN_FREE(sync); 904 return status; 905 } 906 /*====================================================================================*/ 907 bgrt_st_t bgrt_priv_sync_proc_timeout(bgrt_proc_t * proc) 908 { 909 bgrt_st_t status; 910 bgrt_sync_t * sync; 911 912 bgrt_priv_proc_reset_watchdog(); 913 914 status = BGRT_ST_OK; 915 916 if (!proc) 917 { 918 return BGRT_ST_ENULL; 919 } 920 921 BGRT_SPIN_LOCK(proc); 922 sync = proc->sync; 923 BGRT_SPIN_FREE(proc); 924 925 if ((bgrt_sync_t *)0 == sync) /* ADLINT:SL:[W0567] type conversion*/ 926 { 927 BGRT_KERNEL_PREEMPT(); /* ADLINT:SL:[W0705,W0067] OOR access*/ 928 929 BGRT_SPIN_LOCK(proc); 930 931 switch(BGRT_PROC_GET_STATE(proc)) 932 { 933 case BGRT_PROC_STATE_SYNC_WAIT: 934 { 935 /*Is waiting on empty sync, wake up*/ 936 status = BGRT_ST_OK; 937 bgrt_sched_proc_run(proc, BGRT_PROC_STATE_TO_READY); 938 } 939 break; 940 case BGRT_PROC_STATE_SYNC_SLEEP: 941 { 942 /*Blocked on dirty sync, will wakeup soon*/ 943 status = BGRT_ST_OK; 944 } 945 break; 946 default: 947 { 948 /*Something went wrong...*/ 949 status = BGRT_ST_ESYNC; 950 } 951 break; 952 } 953 954 BGRT_SPIN_FREE(proc); 955 return status; 956 } 957 958 BGRT_KERNEL_PREEMPT(); /* ADLINT:SL:[W0705,W0067] OOR access*/ 959 960 BGRT_SPIN_LOCK(sync); 961 BGRT_SPIN_LOCK(proc); 962 963 if (proc->sync != sync) 964 { 965 BGRT_SPIN_FREE(proc); 966 BGRT_SPIN_FREE(sync); 967 968 return BGRT_ST_ESYNC; 969 } 970 else 971 { 972 bgrt_cnt_t pwake; 973 974 pwake = sync->pwake; 975 976 if ((pwake)&&(pwake >= sync->snum)) 977 { 978 /*The process is going to be woken up.*/ 979 BGRT_SPIN_FREE(proc); 980 BGRT_SPIN_FREE(sync); 981 982 return BGRT_ST_OK; 983 } 984 } 985 986 switch(BGRT_PROC_GET_STATE(proc)) 987 { 988 case BGRT_PROC_STATE_SYNC_SLEEP: 989 { 990 /*Undo BGRT_SYNC_SLEEP*/ 991 bgrt_prio_t old_prio; 992 993 BGRT_CNT_DEC(sync->snum); /*One sleeping proc less*/ 994 995 old_prio = BGRT_SYNC_PRIO(sync); 996 997 bgrt_pitem_cut((bgrt_pitem_t *)proc); 998 proc->sync = (bgrt_sync_t *)0; /* ADLINT:SL:[W0567] type conversion*/ 999 bgrt_sched_proc_run(proc, BGRT_PROC_STATE_TO_READY); 1000 BGRT_SPIN_FREE(proc); 1001 1002 proc = sync->owner; 1003 if (proc) 1004 { 1005 bgrt_prio_t new_prio; 1006 1007 new_prio = BGRT_SYNC_PRIO(sync); 1008 if (new_prio != old_prio) 1009 { 1010 BGRT_SPIN_LOCK(proc); 1011 BGRT_PROC_LRES_DEC(proc, old_prio); /* ADLINT:SL:[W1073] int to pointer*/ 1012 BGRT_PROC_LRES_INC(proc, new_prio); 1013 BGRT_SYNC_PI_PRIO_PROPAGATE(proc, sync); /* ADLINT:SL:[W0553] function pointer cast*/ 1014 } 1015 else 1016 { 1017 BGRT_SPIN_FREE(sync); 1018 } 1019 } 1020 else 1021 { 1022 BGRT_SPIN_FREE(sync); 1023 } 1024 return BGRT_ST_OK; 1025 } 1026 1027 case BGRT_PROC_STATE_PI_PEND: /* ADLINT:SL:[W0007] return/break */ 1028 case BGRT_PROC_STATE_PI_READY: /* ADLINT:SL:[W0007] return/break */ 1029 case BGRT_PROC_STATE_PI_RUNNING: /* ADLINT:SL:[W0007] return/break */ 1030 { 1031 BGRT_SPIN_FREE(proc); 1032 BGRT_SPIN_FREE(sync); 1033 1034 return BGRT_ST_EAGAIN; 1035 } 1036 default: /* ADLINT:SL:[W0007] return/break */ 1037 { 1038 BGRT_SPIN_FREE(proc); 1039 BGRT_SPIN_FREE(sync); 1040 1041 return BGRT_ST_OK; 1042 } 1043 } 1044 1045 }