summaryrefslogtreecommitdiff
path: root/console
diff options
context:
space:
mode:
authorMarcus Brinkmann <marcus@gnu.org>2002-06-24 01:05:27 +0000
committerMarcus Brinkmann <marcus@gnu.org>2002-06-24 01:05:27 +0000
commit52be5cefb4852e6c2921fd1b19c4d0b4952860ea (patch)
treec2c5d6d53248df64e218b6148a95c26825a5b5bf /console
parent98f81ca345424f0e3af7bd4c4eb492481b7f3573 (diff)
2002-06-24 Marcus Brinkmann <marcus@gnu.org>
* console.h (cons_color_t): New enum type replacing color macros. (CONS_COLOR_MAX): New macro. (cons_change_t): New type. (struct cons_display): New member CHANGES. * console.c: Include "console.h". (DEFAULT_FOREGROUND, DEFAULT_FOREGROUND_NAME, DEFAULT_BACKGROUND, DEFAULT_BACKGROUND_NAME): New macros. (struct cons): New members foreground and background. (vcons_lookup): Pass colors to display_create invocation. (new_node): Fix st_size for display node. (color_names): New array. (options): Add options to set default foreground and background color. (parse_color): New function. (parse_opt): Implement new options. (netfs_append_args): Add new options to output. (main): Set default colors. * Makefile (DIST_FILES): Remove target. (MIGSTUBS): Remove ourfs_notifyUser.o and add notifyServer.o. * display.c: Do not include "ourfs_notify_U.h". (struct modreq): New member PENDING. (struct notify): New structure. (struct display): New members FILEMOD_REQS_PENDING and NOTIFY_PORT. (pager_read_page): Hand out previously returned pages. (pager_unlock_page): Assert that this is not called. (notify_class, notify_bucket): New port class and bucket global variables. (nowait_file_changed): New function, modified from mig output. (do_mach_notify_port_deleted): New stub function. (do_mach_notify_port_destroyed): New stub function. (do_mach_notify_no_senders): New stub function. (do_mach_notify_dead_name): New stub function. (do_mach_notify_send_once): New stub function. (do_mach_notify_msg_accepted): New function. (service_notifications): New function. (display_notice_changes): Call nowait_file_changed with new argument. Initialize REQ->pending. (display_notice_filechange): Remove arguments except DISPLAY. Set PENDING flags in pending filemod requests. Call nowait_file_changed with new notify argument. If notification will be sent, move modreq structure to pending list. (display_flush_filechange): Rewritten to use ring buffer to store changes. (user_create): Initialize new members of struct cons_display. (display_init): Initialize notify_class and notify_bucket. (display_create): Accept new arguments for default colors. Initialize new members of struct display. (display_destroy): Remove pending filemod requests and destroy the notification port. Do not free the display structure memory. (display_destroy_complete): New function. * display.h: Add new arguments to prototype of display_create.
Diffstat (limited to 'console')
-rw-r--r--console/ChangeLog56
-rw-r--r--console/Makefile3
-rw-r--r--console/console.c90
-rw-r--r--console/console.h46
-rw-r--r--console/display.c436
-rw-r--r--console/display.h5
6 files changed, 520 insertions, 116 deletions
diff --git a/console/ChangeLog b/console/ChangeLog
index 9e86d139..806c95aa 100644
--- a/console/ChangeLog
+++ b/console/ChangeLog
@@ -1,3 +1,59 @@
+2002-06-24 Marcus Brinkmann <marcus@gnu.org>
+
+ * console.h (cons_color_t): New enum type replacing color macros.
+ (CONS_COLOR_MAX): New macro.
+ (cons_change_t): New type.
+ (struct cons_display): New member CHANGES.
+ * console.c: Include "console.h".
+ (DEFAULT_FOREGROUND, DEFAULT_FOREGROUND_NAME, DEFAULT_BACKGROUND,
+ DEFAULT_BACKGROUND_NAME): New macros.
+ (struct cons): New members foreground and background.
+ (vcons_lookup): Pass colors to display_create invocation.
+ (new_node): Fix st_size for display node.
+ (color_names): New array.
+ (options): Add options to set default foreground and background
+ color.
+ (parse_color): New function.
+ (parse_opt): Implement new options.
+ (netfs_append_args): Add new options to output.
+ (main): Set default colors.
+
+ * Makefile (DIST_FILES): Remove target.
+ (MIGSTUBS): Remove ourfs_notifyUser.o and add notifyServer.o.
+ * display.c: Do not include "ourfs_notify_U.h".
+ (struct modreq): New member PENDING.
+ (struct notify): New structure.
+ (struct display): New members FILEMOD_REQS_PENDING and
+ NOTIFY_PORT.
+ (pager_read_page): Hand out previously returned pages.
+ (pager_unlock_page): Assert that this is not called.
+ (notify_class, notify_bucket): New port class and bucket global
+ variables.
+ (nowait_file_changed): New function, modified from mig output.
+ (do_mach_notify_port_deleted): New stub function.
+ (do_mach_notify_port_destroyed): New stub function.
+ (do_mach_notify_no_senders): New stub function.
+ (do_mach_notify_dead_name): New stub function.
+ (do_mach_notify_send_once): New stub function.
+ (do_mach_notify_msg_accepted): New function.
+ (service_notifications): New function.
+ (display_notice_changes): Call nowait_file_changed with new
+ argument. Initialize REQ->pending.
+ (display_notice_filechange): Remove arguments except DISPLAY. Set
+ PENDING flags in pending filemod requests. Call
+ nowait_file_changed with new notify argument. If notification
+ will be sent, move modreq structure to pending list.
+ (display_flush_filechange): Rewritten to use ring buffer to store
+ changes.
+ (user_create): Initialize new members of struct cons_display.
+ (display_init): Initialize notify_class and notify_bucket.
+ (display_create): Accept new arguments for default colors.
+ Initialize new members of struct display.
+ (display_destroy): Remove pending filemod requests and destroy the
+ notification port. Do not free the display structure memory.
+ (display_destroy_complete): New function.
+ * display.h: Add new arguments to prototype of display_create.
+
2002-06-18 Marcus Brinkmann <marcus@gnu.org>
* console.h: Update all CONS_KEY_* macros to match other terminfo
diff --git a/console/Makefile b/console/Makefile
index 2f15f1a1..6498e8e4 100644
--- a/console/Makefile
+++ b/console/Makefile
@@ -25,9 +25,8 @@ target = console
SRCS = console.c display.c input.c
LCLHDRS = console.h display.h input.h
-DIST_FILES = ourfs_notify.defs
-MIGSTUBS = ourfs_notifyUser.o
+MIGSTUBS = notifyServer.o
HURDLIBS = netfs fshelp iohelp threads ports ihash shouldbeinlibc
OBJS = $(sort $(SRCS:.c=.o) $(MIGSTUBS))
diff --git a/console/console.c b/console/console.c
index 8500c84c..43f18e6e 100644
--- a/console/console.c
+++ b/console/console.c
@@ -39,6 +39,8 @@
#include "display.h"
#include "input.h"
+/* We include console.h for the color numbers. */
+#include "console.h"
const char *argp_program_version = STANDARD_HURD_VERSION (console);
@@ -50,6 +52,12 @@ int netfs_maxsymlinks = 16; /* Arbitrary. */
volatile struct mapped_time_value *console_maptime;
#define DEFAULT_ENCODING "ISO-8859-1"
+#define DEFAULT_FOREGROUND CONS_COLOR_WHITE
+/* For the help output. */
+#define DEFAULT_FOREGROUND_NAME "white"
+#define DEFAULT_BACKGROUND CONS_COLOR_BLACK
+/* For the help output. */
+#define DEFAULT_BACKGROUND_NAME "black"
/* A handle for a console device. */
@@ -91,6 +99,9 @@ struct cons
vcons_t vcons_list;
/* The encoding. */
char *encoding;
+ /* Default foreground and background colors. */
+ int foreground;
+ int background;
struct node *node;
mach_port_t underlying;
@@ -163,7 +174,8 @@ vcons_lookup (cons_t cons, int id, int create, vcons_t *r_vcons)
/* XXX Error checking. */
mutex_init (&vcons->lock);
- err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING);
+ err = display_create (&vcons->display, cons->encoding ?: DEFAULT_ENCODING,
+ cons->foreground, cons->background);
if (err)
{
free (vcons->name);
@@ -302,7 +314,7 @@ new_node (struct node **np, vcons_t vcons, vcons_node_type type)
(*np)->nn_stat.st_mode |= S_IFREG;
(*np)->nn_stat.st_mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
(*np)->nn_stat.st_size = 80*50 * (sizeof (wchar_t) + 4)
- + 11 * 4; /* XXX */
+ + 14 * 4 + 512 * 8; /* XXX */
break;
case VCONS_NODE_INPUT:
(*np)->nn_stat.st_ino = (vcons->id << 2) + 3;
@@ -1190,14 +1202,59 @@ netfs_S_file_notice_changes (struct protid *cred, mach_port_t notify)
}
+static const char *color_names[CONS_COLOR_MAX + 1] =
+ {
+ [CONS_COLOR_BLACK] = "black",
+ [CONS_COLOR_RED] = "red",
+ [CONS_COLOR_GREEN] = "green",
+ [CONS_COLOR_YELLOW] = "yellow",
+ [CONS_COLOR_BLUE] = "blue",
+ [CONS_COLOR_MAGENTA] = "magenta",
+ [CONS_COLOR_CYAN] = "cyan",
+ [CONS_COLOR_WHITE] = "white"
+ };
+
static const struct argp_option options[] =
{
- {"encoding", 'e', "NAME", 0, "Set encoding of virtual consoles to"
- " NAME (default `" DEFAULT_ENCODING "')" },
+ { "foreground",'f', "COLOR", 0, "Set foreground color to"
+ " COLOR (default `" DEFAULT_FOREGROUND_NAME "')" },
+ { "background",'b', "COLOR", 0, "Set background color to"
+ " COLOR (default `" DEFAULT_BACKGROUND_NAME "')" },
+ { "encoding", 'e', "NAME", 0, "Set encoding of virtual consoles to"
+ " NAME (default `" DEFAULT_ENCODING "')" },
{0}
};
static error_t
+parse_color (const char *name, int *number)
+{
+ if (isdigit (*name))
+ {
+ long int nr;
+ char *tail;
+
+ errno = 0;
+
+ nr = strtol (name, &tail, 0);
+ if (errno || &tail || nr < 0 || nr > CONS_COLOR_MAX)
+ return EINVAL;
+ *number = nr;
+ return 0;
+ }
+ else
+ {
+ int i;
+ for (i = 0; i <= CONS_COLOR_MAX; i++)
+ if (!strcmp (color_names[i], name))
+ {
+ *number = i;
+ return 0;
+ }
+ return EINVAL;
+ }
+}
+
+static error_t
parse_opt (int opt, char *arg, struct argp_state *state)
{
cons_t cons = state->input;
@@ -1218,6 +1275,11 @@ parse_opt (int opt, char *arg, struct argp_state *state)
mutex_unlock (&cons->lock);
break;
+ case 'f':
+ return parse_color (arg, &cons->foreground);
+ case 'b':
+ return parse_color (arg, &cons->background);
+
case 'e':
/* XXX Check validity of encoding. Can we perform all necessary
conversions? */
@@ -1252,6 +1314,24 @@ netfs_append_args (char **argz, size_t *argz_len)
else
err = errno;
}
+ if (cons->foreground != DEFAULT_FOREGROUND)
+ {
+ char *buf;
+ asprintf (&buf, "--foreground=%s", color_names[cons->foreground]);
+ if (buf)
+ err = argz_add (argz, argz_len, buf);
+ else
+ err = errno;
+ }
+ if (cons->background != DEFAULT_BACKGROUND)
+ {
+ char *buf;
+ asprintf (&buf, "--background=%s", color_names[cons->background]);
+ if (buf)
+ err = argz_add (argz, argz_len, buf);
+ else
+ err = errno;
+ }
return err;
}
@@ -1272,6 +1352,8 @@ main (int argc, char **argv)
error (1, ENOMEM, "Cannot create console structure");
mutex_init (&cons->lock);
cons->encoding = NULL;
+ cons->foreground = DEFAULT_FOREGROUND;
+ cons->background = DEFAULT_BACKGROUND;
cons->vcons_list = NULL;
root_nn.cons = cons;
diff --git a/console/console.h b/console/console.h
index 36ad54a1..81940f9e 100644
--- a/console/console.h
+++ b/console/console.h
@@ -21,14 +21,12 @@
#include <stdint.h>
-#define CONS_COLOR_BLACK 0
-#define CONS_COLOR_RED 1
-#define CONS_COLOR_GREEN 2
-#define CONS_COLOR_YELLOW 3
-#define CONS_COLOR_BLUE 4
-#define CONS_COLOR_MAGENTA 5
-#define CONS_COLOR_CYAN 6
-#define CONS_COLOR_WHITE 7
+typedef enum
+ {
+ CONS_COLOR_BLACK = 0, CONS_COLOR_RED, CONS_COLOR_GREEN, CONS_COLOR_YELLOW,
+ CONS_COLOR_BLUE, CONS_COLOR_MAGENTA, CONS_COLOR_CYAN, CONS_COLOR_WHITE
+ } cons_color_t;
+#define CONS_COLOR_MAX (CONS_COLOR_WHITE)
typedef struct
{
@@ -50,6 +48,25 @@ typedef struct
conchar_attr_t attr;
} conchar_t;
+typedef union
+{
+ struct
+ {
+ /* Only the first 31 bits are available (see WHAT.not_matrix). */
+ uint32_t start;
+ uint32_t end;
+ } matrix;
+ struct
+ {
+ uint32_t cursor_pos : 1;
+ uint32_t cursor_status : 1;
+ uint32_t screen_cur_line : 1;
+ uint32_t screen_scr_lines : 1;
+ uint32_t _unused : 27;
+ uint32_t not_matrix : 1;
+ } what;
+} cons_change_t;
+
struct cons_display
{
#define CONS_MAGIC 0x48555244 /* Hex for "HURD". */
@@ -68,7 +85,7 @@ struct cons_display
uint32_t cur_line; /* Beginning of visible area. This is only
ever increased by the server, so clients
can optimize scrolling. */
- uint32_t scr_lines;/* Number of lines in scrollback buffer
+ uint32_t scr_lines; /* Number of lines in scrollback buffer
preceeding CUR_LINE. */
uint32_t height; /* Number of lines in visible area following
(and including) CUR_LINE. */
@@ -87,6 +104,17 @@ struct cons_display
uint32_t status; /* Visibility status of cursor. */
} cursor;
+ struct
+ {
+ uint32_t buffer; /* Index (in uint32_t) of the beginning of the
+ changes buffer in this structure. */
+ uint32_t length; /* Length of buffer. */
+ uint32_t written; /* Number of records written by server. */
+
+#define _CONS_CHANGES_LENGTH 512
+ cons_change_t _buffer[_CONS_CHANGES_LENGTH];
+ } changes;
+
/* Don't use this, use ((wchar_t *) cons_display +
cons_display.screen.matrix) instead. This will make your client
upward compatible with future versions of this interface. */
diff --git a/console/display.c b/console/display.c
index 5528ff98..a70902c0 100644
--- a/console/display.c
+++ b/console/display.c
@@ -37,8 +37,6 @@
#include <hurd.h>
#include <hurd/pager.h>
-#include "ourfs_notify_U.h"
-
#ifndef __STDC_ISO_10646__
#error It is required that wchar_t is UCS-4.
#endif
@@ -141,6 +139,17 @@ struct modreq
{
mach_port_t port;
struct modreq *next;
+ /* If the port should have been notified, but it was blocking, we
+ set this. */
+ int pending;
+};
+
+/* For each display, a notification port is created to which the
+ kernel sends message accepted notifications. */
+struct notify
+{
+ struct port_info pi;
+ struct display *display;
};
struct display
@@ -166,6 +175,10 @@ struct display
/* A list of ports to send file change notifications to. */
struct modreq *filemod_reqs;
+ /* Those ports which currently have a pending notification. */
+ struct modreq *filemod_reqs_pending;
+ /* The notify port. */
+ struct notify *notify_port;
};
@@ -201,13 +214,17 @@ error_t
pager_read_page (struct user_pager_info *upi, vm_offset_t page,
vm_address_t *buf, int *writelock)
{
- assert (upi->memobj_pages[page / vm_page_size] == (vm_address_t) NULL);
+ /* XXX clients should get a read only object. */
+ *writelock = 0;
- /* This is a read-only medium */
- *writelock = 1;
-
- *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
- MAP_ANON, 0, 0);
+ if (upi->memobj_pages[page / vm_page_size] != (vm_address_t) NULL)
+ {
+ *buf = upi->memobj_pages[page / vm_page_size];
+ upi->memobj_pages[page / vm_page_size] = (vm_address_t) NULL;
+ }
+ else
+ *buf = (vm_address_t) mmap (0, vm_page_size, PROT_READ|PROT_WRITE,
+ MAP_ANON, 0, 0);
return 0;
}
@@ -224,6 +241,7 @@ error_t
pager_unlock_page (struct user_pager_info *pager,
vm_offset_t address)
{
+ assert (!"unlocking requested on unlocked page");
return 0;
}
@@ -258,6 +276,88 @@ service_paging_requests (any_t arg)
}
+/* The bucket and class for notification messages. */
+static struct port_bucket *notify_bucket;
+static struct port_class *notify_class;
+
+#define msgh_request_port msgh_remote_port
+#define msgh_reply_port msgh_local_port
+
+/* SimpleRoutine file_changed */
+kern_return_t
+nowait_file_changed (mach_port_t notify_port, file_changed_type_t change,
+ off_t start, off_t end, mach_port_t notify)
+{
+ typedef struct
+ {
+ mach_msg_header_t Head;
+ mach_msg_type_t changeType;
+ file_changed_type_t change;
+ mach_msg_type_t startType;
+ off_t start;
+ mach_msg_type_t endType;
+ off_t end;
+ } Request;
+ union
+ {
+ Request In;
+ } Mess;
+ register Request *InP = &Mess.In;
+
+ static const mach_msg_type_t changeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ static const mach_msg_type_t startType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ static const mach_msg_type_t endType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ InP->changeType = changeType;
+ InP->change = change;
+ InP->startType = startType;
+ InP->start = start;
+ InP->endType = endType;
+ InP->end = end;
+
+ InP->Head.msgh_bits = MACH_MSGH_BITS(19, 0);
+ /* msgh_size passed as argument. */
+ InP->Head.msgh_request_port = notify_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 20501;
+
+ if (notify == MACH_PORT_NULL)
+ return mach_msg (&InP->Head, MACH_SEND_MSG | MACH_MSG_OPTION_NONE,
+ 48, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL);
+ else
+ return mach_msg (&InP->Head, MACH_SEND_MSG | MACH_SEND_NOTIFY,
+ 48, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
+ notify);
+}
+
/* Free the list of modification requests MR */
static void
free_modreqs (struct modreq *mr)
@@ -271,6 +371,106 @@ free_modreqs (struct modreq *mr)
}
}
+void do_mach_notify_port_deleted (void) { assert (0); }
+void do_mach_notify_port_destroyed (void) { assert (0); }
+void do_mach_notify_no_senders (void) { assert (0); }
+void do_mach_notify_dead_name (void) { assert (0); }
+
+kern_return_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ /* XXX Not sure when this is called. */
+ assert (0);
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (mach_port_t notify, mach_port_t send)
+{
+ struct notify *notify_port = ports_lookup_port (notify_bucket,
+ notify, notify_class);
+ struct display *display;
+ struct modreq **preq;
+ struct modreq *req;
+
+ if (!notify_port)
+ return EOPNOTSUPP;
+
+ /* If we deallocated the send right in display_destroy before the
+ notification was created. We have nothing to do in this
+ case. */
+ if (!send)
+ {
+ assert(0);
+ ports_port_deref (notify_port);
+ return 0;
+ }
+
+ display = notify_port->display;
+ mutex_lock (&display->lock);
+ /* Find request in pending queue. */
+ preq = &display->filemod_reqs_pending;
+ while (*preq && (*preq)->port != send)
+ preq = &(*preq)->next;
+ /* If we don't find the request, it was destroyed in
+ display_destroy. In this case, there is nothing left to do
+ here. */
+ if (! *preq)
+ {
+ assert(0);
+ mutex_unlock (&display->lock);
+ ports_port_deref (notify_port);
+ return 0;
+ }
+ req = *preq;
+
+ if (req->pending)
+ {
+ error_t err;
+ /* A request was desired while we were blocking. Send it now
+ and stay in pending queue. */
+ req->pending = 0;
+ err = nowait_file_changed (req->port, FILE_CHANGED_WRITE, -1, -1,
+ notify);
+ if (err && err != MACH_SEND_WILL_NOTIFY)
+ {
+ *preq = req->next;
+ mutex_unlock (&display->lock);
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ ports_port_deref (notify_port);
+ return err;
+ }
+ if (err == MACH_SEND_WILL_NOTIFY)
+ {
+ mutex_unlock (&display->lock);
+ return 0;
+ }
+ /* The message was succesfully queued, fall through. */
+ }
+ /* Remove request from pending queue. */
+ *preq = req->next;
+ /* Insert request into active queue. */
+ req->next = display->filemod_reqs;
+ display->filemod_reqs = req;
+ mutex_unlock (&display->lock);
+ ports_port_deref (notify_port);
+ return 0;
+}
+
+/* A top-level function for the notification thread that just services
+ notification messages. */
+static void
+service_notifications (any_t arg)
+{
+ struct port_bucket *notify_bucket = arg;
+ extern int notify_server (mach_msg_header_t *inp, mach_msg_header_t *outp);
+
+ for (;;)
+ ports_manage_port_operations_one_thread (notify_bucket,
+ notify_server,
+ 1000 * 60 * 10);
+}
+
error_t
display_notice_changes (display_t display, mach_port_t notify)
{
@@ -278,7 +478,7 @@ display_notice_changes (display_t display, mach_port_t notify)
struct modreq *req;
mutex_lock (&display->lock);
- err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0);
+ err = nowait_file_changed (notify, FILE_CHANGED_NULL, 0, 0, MACH_PORT_NULL);
if (err)
{
mutex_unlock (&display->lock);
@@ -291,6 +491,7 @@ display_notice_changes (display_t display, mach_port_t notify)
return errno;
}
req->port = notify;
+ req->pending = 0;
req->next = display->filemod_reqs;
display->filemod_reqs = req;
mutex_unlock (&display->lock);
@@ -299,24 +500,41 @@ display_notice_changes (display_t display, mach_port_t notify)
/* Requires DISPLAY to be locked. */
static void
-display_notice_filechange (display_t display, enum file_changed_type type,
- off_t start, off_t end)
+display_notice_filechange (display_t display)
{
error_t err;
- struct modreq **preq;
+ struct modreq *req = display->filemod_reqs_pending;
+ struct modreq **preq = &display->filemod_reqs;
+ mach_port_t notify_port = ports_get_right (display->notify_port);
+
+ while (req)
+ {
+ req->pending = 1;
+ req = req->next;
+ }
- preq = &display->filemod_reqs;
while (*preq)
{
- struct modreq *req = *preq;
- err = nowait_file_changed (req->port, type, start, end);
+ req = *preq;
+
+ err = nowait_file_changed (req->port, FILE_CHANGED_WRITE, -1, -1,
+ notify_port);
if (err)
{
/* Remove notify port. */
- *preq = req->next;
- mach_port_deallocate (mach_task_self (), req->port);
- free (req);
- }
+ *preq = req->next;
+
+ if (err == MACH_SEND_WILL_NOTIFY)
+ {
+ req->next = display->filemod_reqs_pending;
+ display->filemod_reqs_pending = req;
+ }
+ else
+ {
+ mach_port_deallocate (mach_task_self (), req->port);
+ free (req);
+ }
+ }
else
preq = &req->next;
}
@@ -326,71 +544,71 @@ static void
display_flush_filechange (display_t display, unsigned int type)
{
struct cons_display *user = display->user;
+ cons_change_t *next = &user->changes._buffer[(user->changes.written + 1)
+ % _CONS_CHANGES_LENGTH];
+ int notify = 0;
+ int bump_written = 0;
if (type & DISPLAY_CHANGE_MATRIX
&& display->changes.which & DISPLAY_CHANGE_MATRIX)
{
- display_notice_filechange (display, FILE_CHANGED_WRITE,
- sizeof (struct cons_display)
- + display->changes.start * sizeof (conchar_t),
- sizeof (struct cons_display)
- + (display->changes.end + 1)
- * sizeof (conchar_t) - 1);
- type &= ~DISPLAY_CHANGE_MATRIX;
+ notify = 1;
+ next->matrix.start = display->changes.start;
+ next->matrix.end = display->changes.end;
+ user->changes.written++;
+ next = &user->changes._buffer[(user->changes.written + 1)
+ % _CONS_CHANGES_LENGTH];
+ display->changes.which &= ~DISPLAY_CHANGE_MATRIX;
}
+ memset (next, 0, sizeof (cons_change_t));
+ next->what.not_matrix = 1;
+
if (type & DISPLAY_CHANGE_CURSOR_POS
- || type & DISPLAY_CHANGE_CURSOR_STATUS)
+ && display->changes.which & DISPLAY_CHANGE_CURSOR_POS
+ && (display->changes.cursor.col != user->cursor.col
+ || display->changes.cursor.row != user->cursor.row))
{
- off_t start;
- off_t len = 0;
+ notify = 1;
+ next->what.cursor_pos = 1;
+ bump_written = 1;
+ display->changes.which &= ~DISPLAY_CHANGE_CURSOR_POS;
+ }
- if (type & DISPLAY_CHANGE_CURSOR_POS
- && display->changes.which & DISPLAY_CHANGE_CURSOR_POS
- && (display->changes.cursor.col != user->cursor.col
- || display->changes.cursor.row != user->cursor.row))
- {
- start = offsetof (struct cons_display, cursor.col);
- len += 2;
- }
- if (type & DISPLAY_CHANGE_CURSOR_STATUS
- && display->changes.which & DISPLAY_CHANGE_CURSOR_STATUS
- && display->changes.cursor.status != user->cursor.status)
- {
- if (!len)
- start = offsetof (struct cons_display, cursor.status);
- len += 1;
- }
- if (len)
- display_notice_filechange (display, FILE_CHANGED_WRITE, start,
- start + len * sizeof (uint32_t) - 1);
+ if (type & DISPLAY_CHANGE_CURSOR_STATUS
+ && display->changes.which & DISPLAY_CHANGE_CURSOR_STATUS
+ && display->changes.cursor.status != user->cursor.status)
+ {
+ notify = 1;
+ next->what.cursor_status = 1;
+ bump_written = 1;
+ display->changes.which &= ~DISPLAY_CHANGE_CURSOR_STATUS;
}
if (type & DISPLAY_CHANGE_SCREEN_CUR_LINE
- || type & DISPLAY_CHANGE_SCREEN_SCR_LINES)
+ && display->changes.which & DISPLAY_CHANGE_SCREEN_CUR_LINE
+ && display->changes.screen.cur_line != user->screen.cur_line)
{
- off_t start;
- off_t len = 0;
+ notify = 1;
+ next->what.screen_cur_line = 1;
+ bump_written = 1;
+ display->changes.which &= ~DISPLAY_CHANGE_SCREEN_CUR_LINE;
+ }
- if (type & DISPLAY_CHANGE_SCREEN_CUR_LINE
- && display->changes.which & DISPLAY_CHANGE_SCREEN_CUR_LINE
- && display->changes.screen.cur_line != user->screen.cur_line)
- {
- start = offsetof (struct cons_display, screen.cur_line);
- len += 2;
- }
- if (type & DISPLAY_CHANGE_SCREEN_SCR_LINES
- && display->changes.which & DISPLAY_CHANGE_SCREEN_SCR_LINES
- && display->changes.screen.scr_lines != user->screen.scr_lines)
- {
- if (!len)
- start = offsetof (struct cons_display, screen.scr_lines);
- len += 1;
- }
- if (len)
- display_notice_filechange (display, FILE_CHANGED_WRITE, start,
- start + len * sizeof (uint32_t) - 1);
+ if (type & DISPLAY_CHANGE_SCREEN_SCR_LINES
+ && display->changes.which & DISPLAY_CHANGE_SCREEN_SCR_LINES
+ && display->changes.screen.scr_lines != user->screen.scr_lines)
+ {
+ notify = 1;
+ next->what.screen_scr_lines = 1;
+ bump_written = 1;
+ display->changes.which &= ~DISPLAY_CHANGE_SCREEN_SCR_LINES;
}
+
+ if (bump_written)
+ user->changes.written++;
+ if (notify)
+ display_notice_filechange (display);
}
/* Record a change in the matrix ringbuffer. */
@@ -536,6 +754,9 @@ user_create (display_t display, uint32_t width, uint32_t height,
user->magic = CONS_MAGIC;
user->version = CONS_VERSION_MAJ << 16 | CONS_VERSION_AGE;
+ user->changes.buffer = offsetof (struct cons_display, changes._buffer)
+ / sizeof (uint32_t);
+ user->changes.length = _CONS_CHANGES_LENGTH;
user->screen.width = width;
user->screen.height = height;
user->screen.lines = lines;
@@ -619,19 +840,6 @@ screen_shift_left (display_t display, size_t col1, size_t row1, size_t col2,
}
display_record_filechange (display, start, end);
-#if 0
- display_flush_filechange (display, DISPLAY_CHANGE_MATRIX);
- display_notice_filechange (display, FILE_CHANGED_TRUNCATE,
- sizeof (struct cons_display)
- + start * sizeof (conchar_t),
- sizeof (struct cons_display)
- + (start + shift) * sizeof (conchar_t) - 1);
- display_notice_filechange (display, FILE_CHANGED_EXTEND,
- sizeof (struct cons_display)
- + (end - shift + 1) * sizeof (conchar_t),
- sizeof (struct cons_display)
- + (end + 1) * sizeof (conchar_t) - 1);
-#endif
}
else
screen_fill (display, col1, row1, col2, row2, chr, attr);
@@ -669,19 +877,6 @@ screen_shift_right (display_t display, size_t col1, size_t row1, size_t col2,
}
display_record_filechange (display, start, end);
-#if 0
- display_flush_filechange (display, DISPLAY_CHANGE_MATRIX);
- display_notice_filechange (display, FILE_CHANGED_EXTEND,
- sizeof (struct cons_display)
- + start * sizeof (conchar_t),
- sizeof (struct cons_display)
- + (start + shift) * sizeof (conchar_t) - 1);
- display_notice_filechange (display, FILE_CHANGED_TRUNCATE,
- sizeof (struct cons_display)
- + (end - shift + 1) * sizeof (conchar_t),
- sizeof (struct cons_display)
- + (end + 1) * sizeof (conchar_t) - 1);
-#endif
}
else
screen_fill (display, col1, row1, col2, row2, chr, attr);
@@ -1395,6 +1590,9 @@ display_output_some (display_t display, char **buffer, size_t *length)
}
+/* Forward declaration. */
+void display_destroy_complete (void *pi);
+
void
display_init (void)
{
@@ -1405,14 +1603,26 @@ display_init (void)
/* Make a thread to service paging requests. */
cthread_detach (cthread_fork ((cthread_fn_t) service_paging_requests,
- (any_t)pager_bucket));
+ (any_t) pager_bucket));
+
+ /* Create the notify bucket, and start to serve notifications. */
+ notify_bucket = ports_create_bucket ();
+ if (! notify_bucket)
+ error (5, errno, "Cannot create notify bucket");
+ notify_class = ports_create_class (display_destroy_complete, NULL);
+ if (! notify_class)
+ error (5, errno, "Cannot create notify class");
+
+ cthread_detach (cthread_fork ((cthread_fn_t) service_notifications,
+ (any_t) notify_bucket));
}
/* Create a new virtual console display, with the system encoding
being ENCODING. */
error_t
-display_create (display_t *r_display, const char *encoding)
+display_create (display_t *r_display, const char *encoding,
+ int foreground, int background)
{
error_t err = 0;
display_t display;
@@ -1425,15 +1635,25 @@ display_create (display_t *r_display, const char *encoding)
if (!display)
return ENOMEM;
+ err = ports_create_port (notify_class, notify_bucket, sizeof (struct notify),
+ &display->notify_port);
+ if (err)
+ {
+ free (display);
+ return err;
+ }
+ display->notify_port->display = display;
+
mutex_init (&display->lock);
- display->attr.bgcol_def = CONS_COLOR_BLACK;
- display->attr.fgcol_def = CONS_COLOR_WHITE;
+ display->attr.bgcol_def = background;
+ display->attr.fgcol_def = foreground;
display->attr.current.bgcol = display->attr.bgcol_def;
display->attr.current.fgcol = display->attr.fgcol_def;
err = user_create (display, width, height, lines, L' ',
display->attr.current);
if (err)
{
+ ports_destroy_right (display->notify_port);
free (display);
return err;
}
@@ -1442,6 +1662,7 @@ display_create (display_t *r_display, const char *encoding)
if (err)
{
user_destroy (display);
+ ports_destroy_right (display->notify_port);
free (display);
}
*r_display = display;
@@ -1453,10 +1674,27 @@ display_create (display_t *r_display, const char *encoding)
void
display_destroy (display_t display)
{
+ if (display->filemod_reqs_pending)
+ free_modreqs (display->filemod_reqs_pending);
if (display->filemod_reqs)
free_modreqs (display->filemod_reqs);
+ ports_destroy_right (display->notify_port);
output_deinit (&display->output);
user_destroy (display);
+ /* We can not free the display structure here, because it might
+ still be needed by pending modification requests when msg
+ accepted notifications are handled. So we have to wait until all
+ notifications have arrived and the notify port is completely
+ deallocated, which will invoke display_destroy_complete
+ below. */
+}
+
+
+/* Complete destruction of the display DISPLAY. */
+void
+display_destroy_complete (void *pi)
+{
+ struct display *display = ((struct notify *) pi)->display;
free (display);
}
diff --git a/console/display.h b/console/display.h
index 303c42e2..4f9b7586 100644
--- a/console/display.h
+++ b/console/display.h
@@ -29,8 +29,9 @@ typedef struct display *display_t;
void display_init (void);
/* Create a new virtual console display, with the system encoding
- being ENCODING. */
-error_t display_create (display_t *r_display, const char *encoding);
+ being ENCODING and the default colors being FOREGROUND and BACKGROUND. */
+error_t display_create (display_t *r_display, const char *encoding,
+ int foreground, int background);
/* Destroy the display DISPLAY. */
void display_destroy (display_t display);