Annotation of prex/usr/server/fs/vfs/vfs_task.c, Revision 1.1
1.1 ! nbrk 1: /*-
! 2: * Copyright (c) 2007, Kohsuke Ohtani All rights reserved.
! 3: *
! 4: * Redistribution and use in source and binary forms, with or without
! 5: * modification, are permitted provided that the following conditions
! 6: * are met:
! 7: * 1. Redistributions of source code must retain the above copyright
! 8: * notice, this list of conditions and the following disclaimer.
! 9: * 2. Redistributions in binary form must reproduce the above copyright
! 10: * notice, this list of conditions and the following disclaimer in the
! 11: * documentation and/or other materials provided with the distribution.
! 12: * 3. Neither the name of the author nor the names of any co-contributors
! 13: * may be used to endorse or promote products derived from this software
! 14: * without specific prior written permission.
! 15: *
! 16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 26: * SUCH DAMAGE.
! 27: */
! 28:
! 29: /*
! 30: * task.c - Routines to manage the per task data.
! 31: */
! 32:
! 33: #include <prex/prex.h>
! 34: #include <sys/list.h>
! 35:
! 36: #include <limits.h>
! 37: #include <stdlib.h>
! 38: #include <string.h>
! 39: #include <stdio.h>
! 40: #include <errno.h>
! 41:
! 42: #include "vfs.h"
! 43:
! 44: #define TASK_MAXBUCKETS 32 /* number of task hash buckets */
! 45:
! 46: #define TASKHASH(x) (int)((x) & (TASK_MAXBUCKETS - 1))
! 47:
! 48: /*
! 49: * Hash table for task.
! 50: */
! 51: static struct list task_table[TASK_MAXBUCKETS];
! 52:
! 53: /*
! 54: * Global lock for task access.
! 55: */
! 56: #if CONFIG_FS_THREADS > 1
! 57: static mutex_t task_lock = MUTEX_INITIALIZER;
! 58: #define TASK_LOCK() mutex_lock(&task_lock)
! 59: #define TASK_UNLOCK() mutex_unlock(&task_lock)
! 60: #else
! 61: #define TASK_LOCK()
! 62: #define TASK_UNLOCK()
! 63: #endif
! 64:
! 65: /*
! 66: * Convert task ID to a task structure.
! 67: * Returns locked task. Caller must unlock it after using it.
! 68: */
! 69: struct task *
! 70: task_lookup(task_t task)
! 71: {
! 72: list_t head, n;
! 73: struct task *t;
! 74:
! 75: if (task == TASK_NULL)
! 76: return NULL;
! 77:
! 78: TASK_LOCK();
! 79: head = &task_table[TASKHASH(task)];
! 80: for (n = list_first(head); n != head; n = list_next(n)) {
! 81: t = list_entry(n, struct task, link);
! 82: ASSERT(t->task);
! 83: if (t->task == task) {
! 84: TASK_UNLOCK();
! 85: mutex_lock(&t->lock);
! 86: return t;
! 87: }
! 88: }
! 89: TASK_UNLOCK();
! 90:
! 91: /* Not found */
! 92: return NULL;
! 93: }
! 94:
! 95: /*
! 96: * Allocate new task
! 97: */
! 98: int
! 99: task_alloc(task_t task, struct task **pt)
! 100: {
! 101: struct task *t;
! 102:
! 103: /* Check if specified task already exists. */
! 104: if (task_lookup(task) != NULL)
! 105: return EINVAL;
! 106:
! 107: if (!(t = malloc(sizeof(struct task))))
! 108: return ENOMEM;
! 109: memset(t, 0, sizeof(struct task));
! 110: t->task = task;
! 111: strcpy(t->cwd, "/");
! 112: mutex_init(&t->lock);
! 113:
! 114: TASK_LOCK();
! 115: list_insert(&task_table[TASKHASH(task)], &t->link);
! 116: TASK_UNLOCK();
! 117: *pt = t;
! 118: return 0;
! 119: }
! 120:
! 121: /*
! 122: * Free needless task.
! 123: */
! 124: void
! 125: task_free(struct task *t)
! 126: {
! 127:
! 128: TASK_LOCK();
! 129: list_remove(&t->link);
! 130: mutex_unlock(&t->lock);
! 131: mutex_destroy(&t->lock);
! 132: free(t);
! 133: TASK_UNLOCK();
! 134: }
! 135:
! 136: /*
! 137: * Update task id of the specified task.
! 138: */
! 139: void
! 140: task_update(struct task *t, task_t task)
! 141: {
! 142:
! 143: TASK_LOCK();
! 144: list_remove(&t->link);
! 145: t->task = task;
! 146: list_insert(&task_table[TASKHASH(task)], &t->link);
! 147: TASK_UNLOCK();
! 148: }
! 149:
! 150: void
! 151: task_unlock(struct task *t)
! 152: {
! 153:
! 154: mutex_unlock(&t->lock);
! 155: }
! 156:
! 157: /*
! 158: * Get file pointer from task/fd pair.
! 159: */
! 160: file_t
! 161: task_getfp(struct task *t, int fd)
! 162: {
! 163:
! 164: if (fd >= OPEN_MAX)
! 165: return NULL;
! 166:
! 167: return t->file[fd];
! 168: }
! 169:
! 170: /*
! 171: * Get new file descriptor in the task.
! 172: * Find the smallest empty slot in the fd array.
! 173: * Returns -1 if there is no empty slot.
! 174: */
! 175: int
! 176: task_newfd(struct task *t)
! 177: {
! 178: int fd;
! 179:
! 180: for (fd = 0; fd < OPEN_MAX; fd++)
! 181: if (t->file[fd] == NULL)
! 182: break;
! 183: if (fd == OPEN_MAX)
! 184: return -1; /* slot full */
! 185:
! 186: return fd;
! 187: }
! 188:
! 189: /*
! 190: * Convert to full path from the cwd of task and path.
! 191: * @t: task structure
! 192: * @path: target path
! 193: * @full: full path to be returned
! 194: */
! 195: int
! 196: task_conv(struct task *t, char *path, char *full)
! 197: {
! 198: char *src, *tgt, *p, *end, *cwd;
! 199: size_t len = 0;
! 200:
! 201: cwd = t->cwd;
! 202: path[PATH_MAX - 1] = '\0';
! 203: len = strlen(path);
! 204: if (len >= PATH_MAX)
! 205: return ENAMETOOLONG;
! 206: if (strlen(cwd) + len >= PATH_MAX)
! 207: return ENAMETOOLONG;
! 208: src = path;
! 209: tgt = full;
! 210: end = src + len;
! 211: if (path[0] == '/') {
! 212: *tgt++ = *src++;
! 213: len++;
! 214: } else {
! 215: strcpy(full, cwd);
! 216: len = strlen(cwd);
! 217: tgt += len;
! 218: if (len > 1 && path[0] != '.') {
! 219: *tgt = '/';
! 220: tgt++;
! 221: len++;
! 222: }
! 223: }
! 224: while (*src) {
! 225: p = src;
! 226: while (*p != '/' && *p != '\0')
! 227: p++;
! 228: *p = '\0';
! 229: if (!strcmp(src, "..")) {
! 230: if (len >= 2) {
! 231: len -= 2;
! 232: tgt -= 2; /* skip previous '/' */
! 233: while (*tgt != '/') {
! 234: tgt--;
! 235: len--;
! 236: }
! 237: if (len == 0) {
! 238: tgt++;
! 239: len++;
! 240: }
! 241: }
! 242: } else if (!strcmp(src, ".")) {
! 243: /* Ignore "." */
! 244: } else {
! 245: while (*src != '\0') {
! 246: *tgt++ = *src++;
! 247: len++;
! 248: }
! 249: }
! 250: if (p == end)
! 251: break;
! 252: if (len > 0 && *(tgt - 1) != '/') {
! 253: *tgt++ = '/';
! 254: len++;
! 255: }
! 256: src = p + 1;
! 257: }
! 258: *tgt = '\0';
! 259: return 0;
! 260: }
! 261:
! 262: #ifdef DEBUG
! 263: void
! 264: task_dump(void)
! 265: {
! 266: #ifdef DEBUG_VFS
! 267: list_t head, n;
! 268: struct task *t;
! 269: int i;
! 270:
! 271: TASK_LOCK();
! 272: dprintf("Dump file data\n");
! 273: dprintf(" task opens cwd\n");
! 274: dprintf(" -------- ------- ------------------------------\n");
! 275: for (i = 0; i < TASK_MAXBUCKETS; i++) {
! 276: head = &task_table[i];
! 277: for (n = list_first(head); n != head; n = list_next(n)) {
! 278: t = list_entry(n, struct task, link);
! 279: dprintf(" %08x %7x %s\n", (int)t->task, t->nopens,
! 280: t->cwd);
! 281: }
! 282: }
! 283: dprintf("\n");
! 284: TASK_UNLOCK();
! 285: #endif
! 286: }
! 287: #endif
! 288:
! 289: void
! 290: task_init(void)
! 291: {
! 292: int i;
! 293:
! 294: for (i = 0; i < TASK_MAXBUCKETS; i++)
! 295: list_init(&task_table[i]);
! 296: }
! 297:
! 298: #ifdef DEBUG_VFS
! 299: void
! 300: task_debug(void)
! 301: {
! 302: int i;
! 303: list_t head;
! 304:
! 305: for (i = 0; i < TASK_MAXBUCKETS; i++) {
! 306: head = &task_table[i];
! 307: dprintf("head=%x head->next=%x head->prev=%x\n", head,
! 308: head->next, head->prev);
! 309: ASSERT(head->next);
! 310: ASSERT(head->prev);
! 311: }
! 312: }
! 313: #endif
CVSweb