openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

resource.c (3813B)


      1 /* Copyright 1998-1999, Brian J. Swetland. All rights reserved.
      2 ** Distributed under the terms of the OpenBLT License
      3 */
      4 
      5 #include "kernel.h"
      6 #include "memory.h"
      7 #include "resource.h"
      8 #include "team.h"
      9 
     10 typedef struct _rtab {
     11     resource_t *resource;
     12     int next;
     13 } rtab;
     14 
     15 static resource_t null_resource;
     16 	
     17 static rtab *rmap;
     18 static uint32 rmax = 0;
     19 static uint32 rfree = 0;
     20 
     21 list_t resource_list;
     22 
     23 void rsrc_init(void *map, int size)
     24 {
     25     int i;
     26 
     27 	list_init(&resource_list);
     28 	
     29     null_resource.id = 0;
     30     null_resource.type = RSRC_NONE;
     31     null_resource.owner = NULL;
     32 	list_init(&null_resource.rights);
     33     
     34     rfree = 1;    
     35     rmax = size / sizeof(rtab);
     36     rmap = (rtab *) map;
     37     for(i = 0; i < rmax; i++) {
     38         rmap[i].resource = &null_resource;
     39         rmap[i].next = i+1;        
     40     }
     41     rmap[rmax-1].next = 0;            
     42 }
     43 
     44 void *rsrc_find(int type, int id)
     45 {    
     46     if((id < rmax) && (rmap[id].resource->type == type)) {
     47         return rmap[id].resource;
     48     } else {
     49         return NULL;    
     50     }
     51 }
     52 
     53 void rsrc_set_owner(resource_t *r, team_t *owner) 
     54 {
     55     if(r->owner) list_remove(&r->owner->resources, r);
     56 	if(r->owner = owner) list_add_tail(&owner->resources, r);
     57 }
     58 
     59 int rsrc_identify(uint32 id) 
     60 {
     61     if((id >= rmax) || (rmap[id].resource->type == RSRC_NONE)) return 0;
     62     return rmap[id].resource->owner->rsrc.id; 
     63 }
     64 
     65 int queue_create(const char *name, team_t *team)
     66 {
     67 	resource_t *rsrc = (resource_t*) kmalloc(resource_t);
     68 	rsrc_bind(rsrc,RSRC_QUEUE,team);
     69 	rsrc_set_name(rsrc,name);
     70 	return rsrc->id;
     71 }
     72 
     73 void rsrc_bind(resource_t *rsrc, rsrc_type type, team_t *owner)
     74 {
     75     uint32 id;
     76     
     77     if(rfree){
     78         id = rfree;
     79         rfree = rmap[rfree].next;
     80     } else {
     81         panic("resource exhaustion");
     82     }
     83     
     84     rmap[id].resource = rsrc;
     85     rsrc->id = id;
     86     rsrc->type = type;
     87     rsrc->owner = owner;
     88 	rsrc->name[0] = 0;
     89 	
     90 	list_init(&rsrc->queue);
     91 	list_init(&rsrc->rights);
     92 	
     93     if(owner) list_add_tail(&owner->resources, rsrc);
     94 	
     95 	list_add_tail(&resource_list, rsrc);
     96 }
     97 
     98 void rsrc_release(resource_t *r)
     99 {
    100     uint32 id = r->id;
    101     task_t *t;
    102 	
    103 	/* unchain it from the owner */
    104     if(r->owner) list_remove(&r->owner->resources, r);
    105 	
    106 	/* unchain it from the global pool */
    107 	list_remove(&resource_list, r);
    108     
    109 	/* wake all blocking objects */
    110 	while((t = list_detach_head(&r->queue))) {
    111 		task_wake(t,ERR_RESOURCE);
    112 	}
    113 	
    114     r->type = RSRC_NONE;
    115     r->id = 0;
    116 	rmap[id].resource = &null_resource;
    117 	rmap[id].next = rfree;
    118     rfree = id;
    119 }
    120 
    121 void rsrc_set_name(resource_t *r, const char *name)
    122 {
    123 	if(name){
    124 		int i;
    125 		for(i=0;*name && (i<31);i++){
    126 			r->name[i] = *name;
    127 			name++;
    128 		}
    129 		r->name[i] = 0;
    130 	} else {
    131 		r->name[0] = 0;
    132 	}
    133 }
    134 
    135 void rsrc_enqueue_ordered(resource_t *rsrc, task_t *task, uint32 wake_time)
    136 {
    137 /* XXX fixme*/
    138 	list_attach_tail(&rsrc->queue, &task->node);
    139 	task->wait_time = wake_time;
    140 	task->flags = tWAITING;
    141 	task->waiting_on = rsrc;	
    142 }
    143 
    144 void rsrc_enqueue(resource_t *rsrc, task_t *task)
    145 {
    146 	task->wait_time = 0;
    147 	task->flags = tWAITING;
    148 	task->waiting_on = rsrc;
    149 	list_attach_tail(&rsrc->queue,&task->node);
    150 }
    151 
    152 task_t *rsrc_dequeue(resource_t *rsrc)
    153 {
    154 	task_t *task = (task_t *) list_detach_head(&rsrc->queue);
    155 	if(task){
    156 		task->waiting_on = NULL;
    157 		task->flags = tREADY;
    158 	}
    159 	return task;
    160 }
    161 
    162 task_t *rsrc_queue_peek(resource_t *rsrc)
    163 {
    164 	if(rsrc->queue.next != (node_t*) &rsrc->queue) {
    165 		return (task_t*) rsrc->queue.next->data;
    166 	}
    167 }
    168 
    169 const char *rsrc_typename(resource_t *rsrc)
    170 {
    171 	switch(rsrc->type){
    172 	case RSRC_NONE: return "none";
    173 	case RSRC_TASK: return "task";
    174 	case RSRC_ASPACE: return "aspace";
    175 	case RSRC_PORT: return "port";
    176 	case RSRC_SEM: return "sem";
    177 	case RSRC_RIGHT: return "right";
    178 	case RSRC_AREA: return "area";
    179 	case RSRC_QUEUE: return "queue";
    180 	case RSRC_TEAM: return "team";
    181 	default: return "????";
    182 	}
    183 }