Fork me on GitHub

root/kernel/sleep.c

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

DEFINITIONS

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

   1 /*
   2  * fiwix/kernel/sleep.c
   3  *
   4  * Copyright 2018, 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 static unsigned int area = 0;
  23 
  24 int sleep(void *address, int state)
  25 {
  26         unsigned long int flags;
  27         struct proc **h;
  28         int signum, i;
  29 
  30         /* return if it has signals */
  31         if(state == PROC_INTERRUPTIBLE) {
  32                 if((signum = issig())) {
  33                         return signum;
  34                 }
  35         }
  36 
  37         if(current->state == PROC_SLEEPING) {
  38                 printk("WARNING: %s(): process with pid '%d' is already sleeping!\n", __FUNCTION__, current->pid);
  39                 return 0;
  40         }
  41 
  42         SAVE_FLAGS(flags); CLI();
  43         i = SLEEP_HASH((unsigned int)address);
  44         h = &sleep_hash_table[i];
  45 
  46         /* insert process in the head */
  47         if(!*h) {
  48                 *h = current;
  49                 (*h)->sleep_prev = (*h)->sleep_next = NULL;
  50         } else {
  51                 current->sleep_prev = NULL;
  52                 current->sleep_next = *h;
  53                 (*h)->sleep_prev = current;
  54                 *h = current;
  55         }
  56         current->sleep_address = address;
  57         current->state = PROC_SLEEPING;
  58 
  59         do_sched();
  60 
  61         signum = 0;
  62         if(state == PROC_INTERRUPTIBLE) {
  63                 signum = issig();
  64         }
  65 
  66         RESTORE_FLAGS(flags);
  67         return signum;
  68 }
  69 
  70 void wakeup(void *address)
  71 {
  72         unsigned long int flags;
  73         struct proc **h;
  74         int i;
  75 
  76         SAVE_FLAGS(flags); CLI();
  77         i = SLEEP_HASH((unsigned int)address);
  78         h = &sleep_hash_table[i];
  79 
  80         while(*h) {
  81                 if((*h)->sleep_address == address) {
  82                         (*h)->sleep_address = NULL;
  83                         (*h)->state = PROC_RUNNING;
  84                         need_resched = 1;
  85                         if((*h)->sleep_next) {
  86                                 (*h)->sleep_next->sleep_prev = (*h)->sleep_prev;
  87                         }
  88                         if((*h)->sleep_prev) {
  89                                 (*h)->sleep_prev->sleep_next = (*h)->sleep_next;
  90                         }
  91                         if(h == &sleep_hash_table[i]) { /* if it's the head */
  92                                 *h = (*h)->sleep_next;
  93                                 continue;
  94                         }
  95                 }
  96                 if(*h) {
  97                         h = &(*h)->sleep_next;
  98                 }
  99         }
 100         RESTORE_FLAGS(flags);
 101 }
 102 
 103 void wakeup_proc(struct proc *p)
 104 {
 105         unsigned long int flags;
 106         struct proc **h;
 107         int i;
 108 
 109         if(p->state != PROC_SLEEPING && p->state != PROC_STOPPED) {
 110                 return;
 111         }
 112 
 113         SAVE_FLAGS(flags); CLI();
 114 
 115         /* stopped processes don't have sleep address */
 116         if(p->sleep_address) {
 117                 if(p->sleep_next) {
 118                         p->sleep_next->sleep_prev = p->sleep_prev;
 119                 }
 120                 if(p->sleep_prev) {
 121                         p->sleep_prev->sleep_next = p->sleep_next;
 122                 }
 123 
 124                 i = SLEEP_HASH((unsigned int)p->sleep_address);
 125                 h = &sleep_hash_table[i];
 126                 if(*h == p) {   /* if it's the head */
 127                         *h = (*h)->sleep_next;
 128                 }
 129         }
 130         p->sleep_address = NULL;
 131         p->state = PROC_RUNNING;
 132         need_resched = 1;
 133 
 134         RESTORE_FLAGS(flags);
 135         return;
 136 }
 137 
 138 void lock_resource(struct resource *resource)
 139 {
 140         unsigned long int flags;
 141 
 142         for(;;) {
 143                 SAVE_FLAGS(flags); CLI();
 144                 if(resource->locked) {
 145                         resource->wanted = 1;
 146                         RESTORE_FLAGS(flags);
 147                         sleep(resource, PROC_UNINTERRUPTIBLE);
 148                 } else {
 149                         break;
 150                 }
 151         }
 152         resource->locked = 1;
 153         RESTORE_FLAGS(flags);
 154 }
 155 
 156 void unlock_resource(struct resource *resource)
 157 {
 158         unsigned long int flags;
 159 
 160         SAVE_FLAGS(flags); CLI();
 161         resource->locked = 0;
 162         if(resource->wanted) {
 163                 resource->wanted = 0;
 164                 wakeup(resource);
 165         }
 166         RESTORE_FLAGS(flags);
 167 }
 168 
 169 int lock_area(unsigned int type)
 170 {
 171         unsigned long int flags;
 172         int retval;
 173 
 174         SAVE_FLAGS(flags); CLI();
 175         retval = area & type;
 176         area |= type;
 177         RESTORE_FLAGS(flags);
 178 
 179         return retval;
 180 }
 181 
 182 int unlock_area(unsigned int type)
 183 {
 184         unsigned long int flags;
 185         int retval;
 186 
 187         SAVE_FLAGS(flags); CLI();
 188         retval = area & type;
 189         area &= ~type;
 190         RESTORE_FLAGS(flags);
 191 
 192         return retval;
 193 }
 194 
 195 void sleep_init(void)
 196 {
 197         memset_b(sleep_hash_table, NULL, sizeof(sleep_hash_table));
 198 }

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