/ kernel / sync.c
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  }