diff --git a/src/system/kernel/port.c b/src/system/kernel/port.c index 9b3b3bf33f..bb8054def8 100644 --- a/src/system/kernel/port.c +++ b/src/system/kernel/port.c @@ -6,7 +6,7 @@ * Distributed under the terms of the NewOS License. */ -/* ports for IPC */ +/*! Ports for IPC */ #include @@ -54,19 +54,14 @@ struct port_entry { struct list msg_queue; }; -// internal API -static int dump_port_list(int argc, char **argv); -static int dump_port_info(int argc, char **argv); -static void _dump_port_info(struct port_entry *port); +#define MAX_QUEUE_LENGTH 4096 +#define PORT_MAX_MESSAGE_SIZE 65536 // sMaxPorts must be power of 2 static int32 sMaxPorts = 4096; static int32 sUsedPorts = 0; -#define MAX_QUEUE_LENGTH 4096 -#define PORT_MAX_MESSAGE_SIZE 65536 - static struct port_entry *sPorts = NULL; static area_id sPortArea = 0; static bool sPortsActive = false; @@ -81,143 +76,7 @@ static spinlock sPortSpinlock = 0; #define RELEASE_PORT_LOCK(s) release_spinlock(&(s).lock) -status_t -port_init(kernel_args *args) -{ - size_t size = sizeof(struct port_entry) * sMaxPorts; - int32 i; - - // create and initialize ports table - sPortArea = create_area("port_table", (void **)&sPorts, B_ANY_KERNEL_ADDRESS, - size, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); - if (sPortArea < 0) { - panic("unable to allocate kernel port table!\n"); - } - - // ToDo: investigate preallocating a list of port_msgs to - // speed up actual message sending/receiving, a slab allocator - // might do it as well, though :-) - - memset(sPorts, 0, size); - for (i = 0; i < sMaxPorts; i++) - sPorts[i].id = -1; - - // add debugger commands - add_debugger_command("ports", &dump_port_list, "Dump a list of all active ports"); - add_debugger_command("port", &dump_port_info, "Dump info about a particular port"); - - sPortsActive = true; - - return 0; -} - - -#ifdef DEBUG -// ToDo: the test code does not belong here! -// the same code is present in the test_app in kernel/apps -// so I guess we can remove this -/* - * testcode - */ - -static int32 port_test_thread_func(void *arg); - -port_id test_p1, test_p2, test_p3, test_p4; - -void -port_test() -{ - char testdata[5]; - thread_id t; - int res; - int32 dummy; - int32 dummy2; - - strcpy(testdata, "abcd"); - - dprintf("porttest: create_port()\n"); - test_p1 = create_port(1, "test port #1"); - test_p2 = create_port(10, "test port #2"); - test_p3 = create_port(1024, "test port #3"); - test_p4 = create_port(1024, "test port #4"); - - dprintf("porttest: find_port()\n"); - dprintf("'test port #1' has id %ld (should be %ld)\n", find_port("test port #1"), test_p1); - - dprintf("porttest: write_port() on 1, 2 and 3\n"); - write_port(test_p1, 1, &testdata, sizeof(testdata)); - write_port(test_p2, 666, &testdata, sizeof(testdata)); - write_port(test_p3, 999, &testdata, sizeof(testdata)); - dprintf("porttest: port_count(test_p1) = %ld\n", port_count(test_p1)); - - dprintf("porttest: write_port() on 1 with timeout of 1 sec (blocks 1 sec)\n"); - write_port_etc(test_p1, 1, &testdata, sizeof(testdata), B_TIMEOUT, 1000000); - dprintf("porttest: write_port() on 2 with timeout of 1 sec (wont block)\n"); - res = write_port_etc(test_p2, 777, &testdata, sizeof(testdata), B_TIMEOUT, 1000000); - dprintf("porttest: res=%d, %s\n", res, res == 0 ? "ok" : "BAD"); - - dprintf("porttest: read_port() on empty port 4 with timeout of 1 sec (blocks 1 sec)\n"); - res = read_port_etc(test_p4, &dummy, &dummy2, sizeof(dummy2), B_TIMEOUT, 1000000); - dprintf("porttest: res=%d, %s\n", res, res == B_TIMED_OUT ? "ok" : "BAD"); - - dprintf("porttest: spawning thread for port 1\n"); - t = spawn_kernel_thread(port_test_thread_func, "port_test", B_NORMAL_PRIORITY, NULL); - resume_thread(t); - - dprintf("porttest: write\n"); - write_port(test_p1, 1, &testdata, sizeof(testdata)); - - // now we can write more (no blocking) - dprintf("porttest: write #2\n"); - write_port(test_p1, 2, &testdata, sizeof(testdata)); - dprintf("porttest: write #3\n"); - write_port(test_p1, 3, &testdata, sizeof(testdata)); - - dprintf("porttest: waiting on spawned thread\n"); - wait_for_thread(t, NULL); - - dprintf("porttest: close p1\n"); - close_port(test_p2); - dprintf("porttest: attempt write p1 after close\n"); - res = write_port(test_p2, 4, &testdata, sizeof(testdata)); - dprintf("porttest: write_port ret %d\n", res); - - dprintf("porttest: testing delete p2\n"); - delete_port(test_p2); - - dprintf("porttest: end test main thread\n"); - -} - - -static int32 -port_test_thread_func(void *arg) -{ - int32 msg_code; - int n; - char buf[6]; - buf[5] = '\0'; - - dprintf("porttest: port_test_thread_func()\n"); - - n = read_port(test_p1, &msg_code, &buf, 3); - dprintf("read_port #1 code %ld len %d buf %s\n", msg_code, n, buf); - n = read_port(test_p1, &msg_code, &buf, 4); - dprintf("read_port #1 code %ld len %d buf %s\n", msg_code, n, buf); - buf[4] = 'X'; - n = read_port(test_p1, &msg_code, &buf, 5); - dprintf("read_port #1 code %ld len %d buf %s\n", msg_code, n, buf); - - dprintf("porttest: testing delete p1 from other thread\n"); - delete_port(test_p1); - dprintf("porttest: end port_test_thread_func()\n"); - - return 0; -} -#endif /* DEBUG */ - - -int +static int dump_port_list(int argc, char **argv) { const char *name = NULL; @@ -241,8 +100,9 @@ dump_port_list(int argc, char **argv) || (name != NULL && strstr(port->name, name) == NULL)) continue; - kprintf("%p %6lx %4ld %6lx %6lx %6lx %s\n", port, port->id, port->capacity, - port->read_sem, port->write_sem, port->owner, port->name); + kprintf("%p %6ld %4ld %6ld %6ld %6ld %s\n", port, port->id, + port->capacity, port->read_sem, port->write_sem, port->owner, + port->name); } return 0; } @@ -293,7 +153,7 @@ dump_port_info(int argc, char **argv) uint32 num = strtoul(argv[1], NULL, 0); uint32 slot = num % sMaxPorts; if (sPorts[slot].id != (int)num) { - kprintf("port 0x%lx doesn't exist!\n", num); + kprintf("port %ld (%#lx) doesn't exist!\n", num, num); return 0; } _dump_port_info(&sPorts[slot]); @@ -303,8 +163,10 @@ dump_port_info(int argc, char **argv) // walk through the ports list, trying to match name for (i = 0; i < sMaxPorts; i++) { - if ((name != NULL && sPorts[i].name != NULL && !strcmp(name, sPorts[i].name)) - || (sem != -1 && (sPorts[i].read_sem == sem || sPorts[i].write_sem == sem))) { + if ((name != NULL && sPorts[i].name != NULL + && !strcmp(name, sPorts[i].name)) + || (sem != -1 && (sPorts[i].read_sem == sem + || sPorts[i].write_sem == sem))) { _dump_port_info(&sPorts[i]); return 0; } @@ -322,10 +184,77 @@ notify_port_select_events(int slot, uint16 events) } -/** this function cycles through the ports table, deleting all - * the ports that are owned by the passed team_id - */ +static void +put_port_msg(port_msg *msg) +{ + cbuf_free_chain(msg->buffer_chain); + free(msg); +} + +static port_msg * +get_port_msg(int32 code, size_t bufferSize) +{ + // ToDo: investigate preallocation of port_msgs (or use a slab allocator) + cbuf *bufferChain = NULL; + + port_msg *msg = (port_msg *)malloc(sizeof(port_msg)); + if (msg == NULL) + return NULL; + + if (bufferSize > 0) { + bufferChain = cbuf_get_chain(bufferSize); + if (bufferChain == NULL) { + free(msg); + return NULL; + } + } + + msg->code = code; + msg->buffer_chain = bufferChain; + msg->size = bufferSize; + return msg; +} + + +/*! You need to own the port's lock when calling this function */ +static bool +is_port_closed(int32 slot) +{ + return sPorts[slot].capacity == 0; +} + + +/*! Fills the port_info structure with information from the specified + port. + The port lock must be held when called. +*/ +static void +fill_port_info(struct port_entry *port, port_info *info, size_t size) +{ + int32 count; + + info->port = port->id; + info->team = port->owner; + info->capacity = port->capacity; + + get_sem_count(port->read_sem, &count); + if (count < 0) + count = 0; + + info->queue_count = count; + info->total_count = port->total_count; + + strlcpy(info->name, port->name, B_OS_NAME_LENGTH); +} + + +// #pragma mark - private kernel API + + +/*! This function cycles through the ports table, deleting all + the ports that are owned by the passed team_id +*/ int delete_owned_ports(team_id owner) { @@ -365,48 +294,6 @@ delete_owned_ports(team_id owner) } -static void -put_port_msg(port_msg *msg) -{ - cbuf_free_chain(msg->buffer_chain); - free(msg); -} - - -static port_msg * -get_port_msg(int32 code, size_t bufferSize) -{ - // ToDo: investigate preallocation of port_msgs (or use a slab allocator) - cbuf *bufferChain = NULL; - - port_msg *msg = (port_msg *)malloc(sizeof(port_msg)); - if (msg == NULL) - return NULL; - - if (bufferSize > 0) { - bufferChain = cbuf_get_chain(bufferSize); - if (bufferChain == NULL) { - free(msg); - return NULL; - } - } - - msg->code = code; - msg->buffer_chain = bufferChain; - msg->size = bufferSize; - return msg; -} - - -/** You need to own the port's lock when calling this function */ - -static bool -is_port_closed(int32 slot) -{ - return sPorts[slot].capacity == 0; -} - - int32 port_max_ports(void) { @@ -421,6 +308,37 @@ port_used_ports(void) } +status_t +port_init(kernel_args *args) +{ + size_t size = sizeof(struct port_entry) * sMaxPorts; + int32 i; + + // create and initialize ports table + sPortArea = create_area("port_table", (void **)&sPorts, B_ANY_KERNEL_ADDRESS, + size, B_FULL_LOCK, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + if (sPortArea < 0) { + panic("unable to allocate kernel port table!\n"); + return sPortArea; + } + + // ToDo: investigate preallocating a list of port_msgs to + // speed up actual message sending/receiving, a slab allocator + // might do it as well, though :-) + + memset(sPorts, 0, size); + for (i = 0; i < sMaxPorts; i++) + sPorts[i].id = -1; + + // add debugger commands + add_debugger_command("ports", &dump_port_list, "Dump a list of all active ports"); + add_debugger_command("port", &dump_port_info, "Dump info about a particular port"); + + sPortsActive = true; + return B_OK; +} + + // #pragma mark - public kernel API @@ -778,31 +696,6 @@ find_port(const char *name) } -/** Fills the port_info structure with information from the specified - * port. - * The port lock must be held when called. - */ - -static void -fill_port_info(struct port_entry *port, port_info *info, size_t size) -{ - int32 count; - - info->port = port->id; - info->team = port->owner; - info->capacity = port->capacity; - - get_sem_count(port->read_sem, &count); - if (count < 0) - count = 0; - - info->queue_count = count; - info->total_count = port->total_count; - - strlcpy(info->name, port->name, B_OS_NAME_LENGTH); -} - - status_t _get_port_info(port_id id, port_info *info, size_t size) { diff --git a/src/system/kernel/team.cpp b/src/system/kernel/team.cpp index 7895313eab..5a6cc4f6bb 100644 --- a/src/system/kernel/team.cpp +++ b/src/system/kernel/team.cpp @@ -6,7 +6,7 @@ * Distributed under the terms of the NewOS License. */ -/* Team functions */ +/*! Team functions */ #include #include @@ -88,27 +88,27 @@ static void _dump_team_info(struct team *team) { kprintf("TEAM: %p\n", team); - kprintf("id: 0x%lx\n", team->id); + kprintf("id: %ld (%#lx)\n", team->id, team->id); kprintf("name: '%s'\n", team->name); kprintf("args: '%s'\n", team->args); kprintf("next: %p\n", team->next); kprintf("parent: %p", team->parent); if (team->parent != NULL) { - kprintf(" (id = 0x%lx)\n", team->parent->id); + kprintf(" (id = %ld)\n", team->parent->id); } else kprintf("\n"); kprintf("children: %p\n", team->children); kprintf("num_threads: %d\n", team->num_threads); kprintf("state: %d\n", team->state); - kprintf("pending_signals: 0x%x\n", team->pending_signals); + kprintf("pending_signals: %#x\n", team->pending_signals); kprintf("io_context: %p\n", team->io_context); if (team->address_space) - kprintf("address_space: %p (id = 0x%lx)\n", team->address_space, team->address_space->id); + kprintf("address_space: %p\n", team->address_space); kprintf("main_thread: %p\n", team->main_thread); kprintf("thread_list: %p\n", team->thread_list); - kprintf("group_id: 0x%lx\n", team->group_id); - kprintf("session_id: 0x%lx\n", team->session_id); + kprintf("group_id: %ld\n", team->group_id); + kprintf("session_id: %ld\n", team->session_id); } @@ -167,12 +167,11 @@ dump_teams(int argc, char **argv) } -/** Frees an array of strings in kernel space. - * - * \param strings strings array - * \param count number of strings in array - */ +/*! Frees an array of strings in kernel space. + \param strings strings array + \param count number of strings in array +*/ static void free_strings_array(char **strings, int32 count) { @@ -188,15 +187,14 @@ free_strings_array(char **strings, int32 count) } -/** Copy an array of strings in kernel space - * - * \param strings strings array to be copied - * \param count number of strings in array - * \param kstrings pointer to the kernel copy - * \return \c B_OK on success, or an appropriate error code on - * failure. - */ +/*! Copy an array of strings in kernel space + \param strings strings array to be copied + \param count number of strings in array + \param kstrings pointer to the kernel copy + \return \c B_OK on success, or an appropriate error code on + failure. +*/ static status_t kernel_copy_strings_array(char * const *in, int32 count, char ***_strings) { @@ -227,15 +225,14 @@ error: } -/** Copy an array of strings from user space to kernel space - * - * \param strings userspace strings array - * \param count number of strings in array - * \param kstrings pointer to the kernel copy - * \return \c B_OK on success, or an appropriate error code on - * failure. - */ +/*! Copy an array of strings from user space to kernel space + \param strings userspace strings array + \param count number of strings in array + \param kstrings pointer to the kernel copy + \return \c B_OK on success, or an appropriate error code on + failure. +*/ static status_t user_copy_strings_array(char * const *userStrings, int32 count, char ***_strings) { @@ -365,9 +362,7 @@ insert_team_into_parent(struct team *parent, struct team *team) } -/** Note: must have TEAM lock held - */ - +/*! Note: must have team lock held */ static void remove_team_from_parent(struct team *parent, struct team *team) { @@ -388,10 +383,9 @@ remove_team_from_parent(struct team *parent, struct team *team) } -/** Reparent each of our children - * Note: must have TEAM lock held - */ - +/*! Reparent each of our children + Note: must have team lock held +*/ static void reparent_children(struct team *team) { @@ -421,8 +415,7 @@ is_process_group_leader(struct team *team) } -/** You must hold the team lock when calling this function. */ - +/*! You must hold the team lock when calling this function. */ static void insert_group_into_session(struct process_session *session, struct process_group *group) { @@ -435,8 +428,7 @@ insert_group_into_session(struct process_session *session, struct process_group } -/** You must hold the team lock when calling this function. */ - +/*! You must hold the team lock when calling this function. */ static void insert_team_into_group(struct process_group *group, struct team *team) { @@ -449,11 +441,10 @@ insert_team_into_group(struct process_group *group, struct team *team) } -/** Removes a group from a session, and puts the session object - * back into the session cache, if it's not used anymore. - * You must hold the team lock when calling this function. - */ - +/*! Removes a group from a session, and puts the session object + back into the session cache, if it's not used anymore. + You must hold the team lock when calling this function. +*/ static void remove_group_from_session(struct process_group *group) { @@ -472,18 +463,15 @@ remove_group_from_session(struct process_group *group) } +/*! Removes the team from the group. If that group becomes therefore + unused, it will set \a _freeGroup to point to the group - otherwise + it will be \c NULL. + It cannot be freed here because this function has to be called + with having the team lock held. - -/** Removes the team from the group. If that group becomes therefore - * unused, it will set \a _freeGroup to point to the group - otherwise - * it will be \c NULL. - * It cannot be freed here because this function has to be called - * with having the team lock held. - * - * \param team the team that'll be removed from it's group - * \param _freeGroup points to the group to be freed or NULL - */ - + \param team the team that'll be removed from it's group + \param _freeGroup points to the group to be freed or NULL +*/ static void remove_team_from_group(struct team *team, struct process_group **_freeGroup) { @@ -865,7 +853,7 @@ team_create_thread_start(void *args) return err; } - TRACE(("team_create_thread_start: loaded elf. entry = 0x%lx\n", entry)); + TRACE(("team_create_thread_start: loaded elf. entry = %#lx\n", entry)); team->state = TEAM_STATE_NORMAL; @@ -875,10 +863,9 @@ team_create_thread_start(void *args) } -/** The BeOS kernel exports a function with this name, but most probably with - * different parameters; we should not make it public. - */ - +/*! The BeOS kernel exports a function with this name, but most probably with + different parameters; we should not make it public. +*/ static thread_id load_image_etc(int32 argCount, char * const *args, int32 envCount, char * const *env, int32 priority, uint32 flags, @@ -1023,12 +1010,11 @@ err1: } -/** Almost shuts down the current team and loads a new image into it. - * If successful, this function does not return and will takeover ownership of - * the arguments provided. - * This function may only be called from user space. - */ - +/*! Almost shuts down the current team and loads a new image into it. + If successful, this function does not return and will takeover ownership of + the arguments provided. + This function may only be called from user space. +*/ static status_t exec_team(const char *path, int32 argCount, char * const *args, int32 envCount, char * const *env) @@ -1041,7 +1027,7 @@ exec_team(const char *path, int32 argCount, char * const *args, struct thread *thread; thread_id nubThreadID = -1; - TRACE(("exec_team(path = \"%s\", argc = %ld, envCount = %ld): team %lx\n", + TRACE(("exec_team(path = \"%s\", argc = %ld, envCount = %ld): team %ld\n", args[0], argCount, envCount, team->id)); // switching the kernel at run time is probably not a good idea :) @@ -1128,12 +1114,11 @@ exec_team(const char *path, int32 argCount, char * const *args, } -/** This is the first function to be called from the newly created - * main child thread. - * It will fill in everything what's left to do from fork_arg, and - * return from the parent's fork() syscall to the child. - */ - +/*! This is the first function to be called from the newly created + main child thread. + It will fill in everything what's left to do from fork_arg, and + return from the parent's fork() syscall to the child. +*/ static int32 fork_team_thread_start(void *_args) { @@ -1175,7 +1160,7 @@ fork_team(void) status_t status; int32 cookie; - TRACE(("fork_team(): team %lx\n", parentTeam->id)); + TRACE(("fork_team(): team %ld\n", parentTeam->id)); if (parentTeam == team_get_kernel_team()) return B_NOT_ALLOWED; @@ -1288,10 +1273,10 @@ err1: } -/** Returns if the specified \a team has any children belonging to the specified \a group. - * Must be called with the team lock held. - */ - +/*! Returns if the specified \a team has any children belonging to the + specified \a group. + Must be called with the team lock held. +*/ static bool has_children_in_group(struct team *parent, pid_t groupID) { @@ -1504,11 +1489,10 @@ wait_for_child(pid_t child, uint32 flags, int32 *_reason, } -/** Fills the team_info structure with information from the specified - * team. - * The team lock must be held when called. - */ - +/*! Fills the team_info structure with information from the specified + team. + The team lock must be held when called. +*/ static status_t fill_team_info(struct team *team, team_info *info, size_t size) { @@ -1675,9 +1659,7 @@ team_get_death_entry(struct team *team, thread_id child, bool* _deleteEntry) } -/** Quick check to see if we have a valid team ID. - */ - +/*! Quick check to see if we have a valid team ID. */ bool team_is_valid(team_id id) { @@ -1709,10 +1691,9 @@ team_get_team_struct_locked(team_id id) } -/** This searches the session of the team for the specified group ID. - * You must hold the team lock when you call this function. - */ - +/*! This searches the session of the team for the specified group ID. + You must hold the team lock when you call this function. +*/ struct process_group * team_get_process_group_locked(struct process_session *session, pid_t id) { @@ -2126,11 +2107,10 @@ team_set_job_control_state(struct team* team, job_control_state newState, } -/** Adds a hook to the team that is called as soon as this - * team goes away. - * This call might get public in the future. - */ - +/*! Adds a hook to the team that is called as soon as this + team goes away. + This call might get public in the future. +*/ status_t start_watching_team(team_id teamID, void (*hook)(team_id, void *), void *data) {