Fork me on GitHub

root/kernel/sleep.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. runnable
  2. not_runnable
  3. sleep
  4. wakeup
  5. wakeup_proc
  6. lock_resource
  7. unlock_resource
  8. lock_area
  9. unlock_area
  10. sleep_init

   1 /*
   2  * fiwix/kernel/sleep.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/asm.h>
   9 #include <fiwix/kernel.h>
  10 #include <fiwix/limits.h>
  11 #include <fiwix/sleep.h>
  12 #include <fiwix/sched.h>
  13 #include <fiwix/signal.h>
  14 #include <fiwix/process.h>
  15 #include <fiwix/stdio.h>
  16 #include <fiwix/string.h>
  17 
  18 #define NR_BUCKETS              ((NR_PROCS * 10) / 100) /* 10% of NR_PROCS */
  19 #define SLEEP_HASH(addr)        ((addr) % (NR_BUCKETS))
  20 
  21 struct proc *sleep_hash_table[NR_BUCKETS];
  22 struct proc *proc_run_head;
  23 static unsigned int area = 0;
  24 
  25 void runnable(struct proc *p)
  26 {
  27         if(p->state == PROC_RUNNING) {
  28                 printk("WARNING: %s(): process with pid '%d' is already running!\n", __FUNCTION__, p->pid);
  29                 return;
  30         }
  31 
  32         if(proc_run_head) {
  33                 p->next_run = proc_run_head;
  34                 proc_run_head->prev_run = p;
  35         }
  36         proc_run_head = p;
  37         p->state = PROC_RUNNING;
  38 }
  39 
  40 void not_runnable(struct proc *p, int state)
  41 {
  42         if(p->next_run) {
  43                 p->next_run->prev_run = p->prev_run;
  44         }
  45         if(p->prev_run) {
  46                 p->prev_run->next_run = p->next_run;
  47         }
  48         if(p == proc_run_head) {
  49                 proc_run_head = p->next_run;
  50         }
  51         p->prev_run = p->next_run = NULL;
  52         p->state = state;
  53 }
  54 
  55 int sleep(void *address, int state)
  56 {
  57         unsigned long int flags;
  58         struct proc **h;
  59         int signum, i;
  60 
  61         /* return if it has signals */
  62         if(state == PROC_INTERRUPTIBLE) {
  63                 if((signum = issig())) {
  64                         return signum;
  65                 }
  66         }
  67 
  68         if(current->state == PROC_SLEEPING) {
  69                 printk("WARNING: %s(): process with pid '%d' is already sleeping!\n", __FUNCTION__, current->pid);
  70                 return 0;
  71         }
  72 
  73         SAVE_FLAGS(flags); CLI();
  74         i = SLEEP_HASH((unsigned int)address);
  75         h = &sleep_hash_table[i];
  76 
  77         /* insert process in the head */
  78         if(!*h) {
  79                 *h = current;
  80                 (*h)->prev_sleep = (*h)->next_sleep = NULL;
  81         } else {
  82                 current->prev_sleep = NULL;
  83                 current->next_sleep = *h;
  84                 (*h)->prev_sleep = current;
  85                 *h = current;
  86         }
  87         current->sleep_address = address;
  88         not_runnable(current, PROC_SLEEPING);
  89 
  90         do_sched();
  91 
  92         signum = 0;
  93         if(state == PROC_INTERRUPTIBLE) {
  94                 signum = issig();
  95         }
  96 
  97         RESTORE_FLAGS(flags);
  98         return signum;
  99 }
 100 
 101 void wakeup(void *address)
 102 {
 103         unsigned long int flags;
 104         struct proc **h;
 105         int i;
 106 
 107         SAVE_FLAGS(flags); CLI();
 108         i = SLEEP_HASH((unsigned int)address);
 109         h = &sleep_hash_table[i];
 110 
 111         while(*h) {
 112                 if((*h)->sleep_address == address) {
 113                         (*h)->sleep_address = NULL;
 114                         (*h)->cpu_count = (*h)->priority;
 115                         runnable(*h);
 116                         need_resched = 1;
 117                         if((*h)->next_sleep) {
 118                                 (*h)->next_sleep->prev_sleep = (*h)->prev_sleep;
 119                         }
 120                         if((*h)->prev_sleep) {
 121                                 (*h)->prev_sleep->next_sleep = (*h)->next_sleep;
 122                         }
 123                         if(h == &sleep_hash_table[i]) { /* if it's the head */
 124                                 *h = (*h)->next_sleep;
 125                                 continue;
 126                         }
 127                 }
 128                 if(*h) {
 129                         h = &(*h)->next_sleep;
 130                 }
 131         }
 132         RESTORE_FLAGS(flags);
 133 }
 134 
 135 void wakeup_proc(struct proc *p)
 136 {
 137         unsigned long int flags;
 138         struct proc **h;
 139         int i;
 140 
 141         if(p->state != PROC_SLEEPING && p->state != PROC_STOPPED) {
 142                 return;
 143         }
 144 
 145         SAVE_FLAGS(flags); CLI();
 146 
 147         /* stopped processes don't have sleep address */
 148         if(p->sleep_address) {
 149                 if(p->next_sleep) {
 150                         p->next_sleep->prev_sleep = p->prev_sleep;
 151                 }
 152                 if(p->prev_sleep) {
 153                         p->prev_sleep->next_sleep = p->next_sleep;
 154                 }
 155 
 156                 i = SLEEP_HASH((unsigned int)p->sleep_address);
 157                 h = &sleep_hash_table[i];
 158 
 159                 if(*h == p) {   /* if it's the head */
 160                         *h = (*h)->next_sleep;
 161                 }
 162         }
 163         p->sleep_address = NULL;
 164         runnable(p);
 165         need_resched = 1;
 166 
 167         RESTORE_FLAGS(flags);
 168 }
 169 
 170 void lock_resource(struct resource *resource)
 171 {
 172         unsigned long int flags;
 173 
 174         for(;;) {
 175                 SAVE_FLAGS(flags); CLI();
 176                 if(resource->locked) {
 177                         resource->wanted = 1;
 178                         RESTORE_FLAGS(flags);
 179                         sleep(resource, PROC_UNINTERRUPTIBLE);
 180                 } else {
 181                         break;
 182                 }
 183         }
 184         resource->locked = 1;
 185         RESTORE_FLAGS(flags);
 186 }
 187 
 188 void unlock_resource(struct resource *resource)
 189 {
 190         unsigned long int flags;
 191 
 192         SAVE_FLAGS(flags); CLI();
 193         resource->locked = 0;
 194         if(resource->wanted) {
 195                 resource->wanted = 0;
 196                 wakeup(resource);
 197         }
 198         RESTORE_FLAGS(flags);
 199 }
 200 
 201 int lock_area(unsigned int type)
 202 {
 203         unsigned long int flags;
 204         int retval;
 205 
 206         SAVE_FLAGS(flags); CLI();
 207         retval = area & type;
 208         area |= type;
 209         RESTORE_FLAGS(flags);
 210 
 211         return retval;
 212 }
 213 
 214 int unlock_area(unsigned int type)
 215 {
 216         unsigned long int flags;
 217         int retval;
 218 
 219         SAVE_FLAGS(flags); CLI();
 220         retval = area & type;
 221         area &= ~type;
 222         RESTORE_FLAGS(flags);
 223 
 224         return retval;
 225 }
 226 
 227 void sleep_init(void)
 228 {
 229         proc_run_head = NULL;
 230         memset_b(sleep_hash_table, NULL, sizeof(sleep_hash_table));
 231 }

/* [previous][next][first][last][top][bottom][index][help] */