Annotation of Gnu-Mach/device/kmsg.c, revision 1.1.1.1

1.1       root        1: /* GNU Mach Kernel Message Device.
                      2:    Copyright (C) 1998, 1999 Free Software Foundation, Inc.
                      3:    Written by OKUJI Yoshinori.
                      4: 
                      5: This 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 2, or (at your option)
                      8: any later version.
                      9: 
                     10: This software 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 the software; see the file COPYING.  If not, write to
                     17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
                     18: 
                     19: /* Now kmsg provides stream interface, not random access methods.  */
                     20: 
                     21: #include <sys/types.h>
                     22: #include <device/conf.h>
                     23: #include <device/io_req.h>
                     24: #include <mach/boolean.h>
                     25: #include <kern/lock.h>
                     26: #include <kmsg.h>
                     27: 
                     28: 
                     29: #define KMSGBUFSIZE    (4096)  /* XXX */
                     30: 
                     31: /* Simple array for buffering messages */
                     32: static char kmsg_buffer[KMSGBUFSIZE];
                     33: /* Point to the offset to write */
                     34: static int kmsg_write_offset;
                     35: /* Point to the offset to read */
                     36: static int kmsg_read_offset;
                     37: /* I/O request queue for blocking read */
                     38: static queue_head_t kmsg_read_queue;
                     39: /* Used for exclusive access to the device */
                     40: static int kmsg_in_use;
                     41: /* Used for exclusive access to the routines */
                     42: static simple_lock_data_t kmsg_lock;
                     43: /* If already initialized or not  */
                     44: static int kmsg_init_done = 0;
                     45: 
                     46: /* Kernel Message Initializer */
                     47: static void
                     48: kmsginit (void)
                     49: {
                     50:   kmsg_write_offset = 0;
                     51:   kmsg_read_offset = 0;
                     52:   queue_init (&kmsg_read_queue);
                     53:   kmsg_in_use = 0;
                     54:   simple_lock_init (&kmsg_lock);
                     55: }
                     56: 
                     57: /* Kernel Message Open Handler */
                     58: io_return_t
                     59: kmsgopen (dev_t dev, int flag, io_req_t ior)
                     60: {
                     61:   simple_lock (&kmsg_lock);
                     62:   if (kmsg_in_use)
                     63:     {
                     64:       simple_unlock (&kmsg_lock);
                     65:       return D_ALREADY_OPEN;
                     66:     }
                     67:   
                     68:   kmsg_in_use = 1;
                     69: 
                     70:   simple_unlock (&kmsg_lock);
                     71:   return D_SUCCESS;
                     72: }
                     73: 
                     74: /* Kernel Message Close Handler */
                     75: io_return_t
                     76: kmsgclose (dev_t dev, int flag)
                     77: {
                     78:   simple_lock (&kmsg_lock);
                     79:   kmsg_in_use = 0;
                     80:   
                     81:   simple_unlock (&kmsg_lock);
                     82:   return D_SUCCESS;
                     83: }
                     84: 
                     85: static boolean_t kmsg_read_done (io_req_t ior);
                     86: 
                     87: /* Kernel Message Read Handler */
                     88: io_return_t
                     89: kmsgread (dev_t dev, io_req_t ior)
                     90: {
                     91:   int err;
                     92:   int amt, len;
                     93:   
                     94:   err = device_read_alloc (ior, ior->io_count);
                     95:   if (err != KERN_SUCCESS)
                     96:     return err;
                     97: 
                     98:   simple_lock (&kmsg_lock);
                     99:   if (kmsg_read_offset == kmsg_write_offset)
                    100:     {
                    101:       /* The queue is empty.  */
                    102:       if (ior->io_mode & D_NOWAIT)
                    103:        {
                    104:          simple_unlock (&kmsg_lock);
                    105:          return D_WOULD_BLOCK;
                    106:        }
                    107: 
                    108:       ior->io_done = kmsg_read_done;
                    109:       enqueue_tail (&kmsg_read_queue, ior);
                    110:       simple_unlock (&kmsg_lock);
                    111:       return D_IO_QUEUED;
                    112:     }
                    113: 
                    114:   len = kmsg_write_offset - kmsg_read_offset;
                    115:   if (len < 0)
                    116:     len += KMSGBUFSIZE;
                    117: 
                    118:   amt = ior->io_count;
                    119:   if (amt > len)
                    120:     amt = len;
                    121:   
                    122:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    123:     {
                    124:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    125:     }
                    126:   else
                    127:     {
                    128:       int cnt;
                    129: 
                    130:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    131:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    132:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    133:     }
                    134: 
                    135:   kmsg_read_offset += amt;
                    136:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    137:     kmsg_read_offset -= KMSGBUFSIZE;
                    138:   
                    139:   ior->io_residual = ior->io_count - amt;
                    140:   
                    141:   simple_unlock (&kmsg_lock);
                    142:   return D_SUCCESS;
                    143: }
                    144: 
                    145: static boolean_t
                    146: kmsg_read_done (io_req_t ior)
                    147: {
                    148:   int err;
                    149:   int amt, len;
                    150: 
                    151:   simple_lock (&kmsg_lock);
                    152:   if (kmsg_read_offset == kmsg_write_offset)
                    153:     {
                    154:       /* The queue is empty.  */
                    155:       ior->io_done = kmsg_read_done;
                    156:       enqueue_tail (&kmsg_read_queue, ior);
                    157:       simple_unlock (&kmsg_lock);
                    158:       return FALSE;
                    159:     }
                    160: 
                    161:   len = kmsg_write_offset - kmsg_read_offset;
                    162:   if (len < 0)
                    163:     len += KMSGBUFSIZE;
                    164: 
                    165:   amt = ior->io_count;
                    166:   if (amt > len)
                    167:     amt = len;
                    168:   
                    169:   if (kmsg_read_offset + amt <= KMSGBUFSIZE)
                    170:     {
                    171:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, amt);
                    172:     }
                    173:   else
                    174:     {
                    175:       int cnt;
                    176: 
                    177:       cnt = KMSGBUFSIZE - kmsg_read_offset;
                    178:       memcpy (ior->io_data, kmsg_buffer + kmsg_read_offset, cnt);
                    179:       memcpy (ior->io_data + cnt, kmsg_buffer, amt - cnt);
                    180:     }
                    181: 
                    182:   kmsg_read_offset += amt;
                    183:   if (kmsg_read_offset >= KMSGBUFSIZE)
                    184:     kmsg_read_offset -= KMSGBUFSIZE;
                    185:   
                    186:   ior->io_residual = ior->io_count - amt;
                    187: 
                    188:   simple_unlock (&kmsg_lock);
                    189:   ds_read_done (ior);
                    190:   
                    191:   return TRUE;
                    192: }
                    193: 
                    194: io_return_t
                    195: kmsggetstat (dev_t dev, int flavor, int *data, unsigned int *count)
                    196: {
                    197:   switch (flavor)
                    198:     {
                    199:     case DEV_GET_SIZE:
                    200:       data[DEV_GET_SIZE_DEVICE_SIZE] = 0;
                    201:       data[DEV_GET_SIZE_RECORD_SIZE] = 1;
                    202:       *count = DEV_GET_SIZE_COUNT;
                    203:       break;
                    204: 
                    205:     default:
                    206:       return D_INVALID_OPERATION;
                    207:     }
                    208: 
                    209:   return D_SUCCESS;
                    210: }
                    211: 
                    212: /* Write to Kernel Message Buffer */
                    213: void
                    214: kmsg_putchar (int c)
                    215: {
                    216:   io_req_t ior;
                    217:   int offset;
                    218: 
                    219:   /* XXX: cninit is not called before cnputc is used. So call kmsginit
                    220:      here if not initialized yet.  */
                    221:   if (!kmsg_init_done)
                    222:     {
                    223:       kmsginit ();
                    224:       kmsg_init_done = 1;
                    225:     }
                    226:   
                    227:   simple_lock (&kmsg_lock);
                    228:   offset = kmsg_write_offset + 1;
                    229:   if (offset == KMSGBUFSIZE)
                    230:     offset = 0;
                    231: 
                    232:   if (offset == kmsg_read_offset)
                    233:     {
                    234:       /* Discard C.  */
                    235:       simple_unlock (&kmsg_lock);
                    236:       return;
                    237:     }
                    238: 
                    239:   kmsg_buffer[kmsg_write_offset++] = c;
                    240:   if (kmsg_write_offset == KMSGBUFSIZE)
                    241:     kmsg_write_offset = 0;
                    242: 
                    243:   while ((ior = (io_req_t) dequeue_head (&kmsg_read_queue)) != NULL)
                    244:     iodone (ior);
                    245: 
                    246:   simple_unlock (&kmsg_lock);
                    247: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.