/*===========================================================================* * subread * *===========================================================================*/ static int subread(struct logdevice *log, size_t size, endpoint_t endpt, cp_grant_id_t grant) { size_t offset, count; char *buf; int r; for (offset = 0; log->log_size > 0 && offset < size; offset += count) { count = size - offset; if (count > log->log_size) count = log->log_size; if (log->log_read + count > LOG_SIZE) count = LOG_SIZE - log->log_read; buf = log->log_buffer + log->log_read; if((r=sys_safecopyto(endpt, grant, offset, (vir_bytes)buf, count)) != OK) return r; LOGINC(log->log_read, count); log->log_size -= count; } return offset; }
/*===========================================================================* * subread * *===========================================================================*/ PRIVATE int subread(struct logdevice *log, int count, endpoint_t endpt, cp_grant_id_t grant, size_t offset) { char *buf; int r; if (count > log->log_size) count = log->log_size; if (log->log_read + count > LOG_SIZE) count = LOG_SIZE - log->log_read; buf = log->log_buffer + log->log_read; if((r=sys_safecopyto(endpt, grant, offset, (vir_bytes)buf, count, D)) != OK) return r; LOGINC(log->log_read, count); log->log_size -= count; return count; }
/*===========================================================================* * subwrite * *===========================================================================*/ PRIVATE int subwrite(struct logdevice *log, int count, endpoint_t endpt, cp_grant_id_t grant, size_t offset, char *localbuf) { int d, r; char *buf; message m; if (log->log_write + count > LOG_SIZE) count = LOG_SIZE - log->log_write; buf = log->log_buffer + log->log_write; if(localbuf != NULL) { memcpy(buf, localbuf, count); } else { if((r=sys_safecopyfrom(endpt, grant, offset, (vir_bytes)buf, count, D)) != OK) return r; } LOGINC(log->log_write, count); log->log_size += count; if(log->log_size > LOG_SIZE) { int overflow; overflow = log->log_size - LOG_SIZE; log->log_size -= overflow; LOGINC(log->log_read, overflow); } if(log->log_size > 0 && log->log_source != NONE && !log->log_revive_alerted) { /* Someone who was suspended on read can now * be revived. */ log->log_status = subread(log, log->log_iosize, log->log_source, log->log_user_grant, log->log_user_offset); m.m_type = DEV_REVIVE; m.REP_ENDPT = log->log_proc_nr; m.REP_STATUS = log->log_status; m.REP_IO_GRANT = log->log_user_grant; r= send(log->log_source, &m); if (r != OK) { printf("log`subwrite: send to %d failed: %d\n", log->log_source, r); } log->log_source = NONE; } if(log->log_size > 0) log->log_select_ready_ops |= SEL_RD; if(log->log_size > 0 && log->log_selected && !(log->log_select_alerted)) { /* Someone(s) who was/were select()ing can now * be awoken. If there was a blocking read (above), * this can only happen if the blocking read didn't * swallow all the data (log_size > 0). */ if(log->log_selected & SEL_RD) { d= log-logdevices; m.m_type = DEV_SEL_REPL2; m.DEV_SEL_OPS = log->log_select_ready_ops; m.DEV_MINOR = d; #if LOG_DEBUG printf("select sending DEV_SEL_REPL2\n"); #endif r= send(log->log_select_proc, &m); if (r != OK) { printf( "log`subwrite: send to %d failed: %d\n", log->log_select_proc, r); } log->log_selected &= ~log->log_select_ready_ops; } } return count; }
/*===========================================================================* * subwrite * *===========================================================================*/ static int subwrite(struct logdevice *log, size_t size, endpoint_t endpt, cp_grant_id_t grant, char *localbuf) { size_t count, offset; int overflow, r, result; devminor_t minor; char *buf; message m; /* With a sufficiently large input size, we might wrap around the ring buffer * multiple times. */ result = 0; for (offset = 0; offset < size; offset += count) { count = size - offset; if (log->log_write + count > LOG_SIZE) count = LOG_SIZE - log->log_write; buf = log->log_buffer + log->log_write; if(localbuf != NULL) { memcpy(buf, localbuf, count); localbuf += count; } else { if((r=sys_safecopyfrom(endpt, grant, offset, (vir_bytes)buf, count)) != OK) { /* return any partial success upon error */ result = (offset > 0) ? (int)offset : r; break; } } LOGINC(log->log_write, count); log->log_size += count; if(log->log_size > LOG_SIZE) { overflow = log->log_size - LOG_SIZE; log->log_size -= overflow; LOGINC(log->log_read, overflow); } result += (int)count; } if (log->log_size > 0 && log->log_source != NONE) { /* Someone who was suspended on read can now be revived. */ r = subread(log, log->log_iosize, log->log_source, log->log_grant); chardriver_reply_task(log->log_source, log->log_id, r); log->log_source = NONE; } if (log->log_size > 0 && (log->log_selected & CDEV_OP_RD)) { /* Someone(s) who was/were select()ing can now be awoken. If there was * a blocking read (above), this can only happen if the blocking read * didn't swallow all the data (log_size > 0). */ minor = log-logdevices; #if LOG_DEBUG printf("select sending CDEV_SEL2_REPLY\n"); #endif chardriver_reply_select(log->log_select_proc, minor, CDEV_OP_RD); log->log_selected &= ~CDEV_OP_RD; } return result; }