/* * This message server catches server exceptions. It runs in a dedicated thread. */ void * server_exception_catcher( void *arg) { struct server_thread_priv_data priv_data; kern_return_t kr; #define MSG_BUFFER_SIZE 8192 union request_msg { mach_msg_header_t hdr; mig_reply_error_t death_pill; char space[MSG_BUFFER_SIZE]; } *msg_buffer_1, *msg_buffer_2; mach_msg_header_t *request; mig_reply_error_t *reply; cthread_set_name(cthread_self(), "server exc catcher"); server_thread_set_priv_data(cthread_self(), &priv_data); kr = vm_allocate(mach_task_self(), (vm_address_t *) &msg_buffer_1, 2 * sizeof *msg_buffer_1, TRUE); if (kr != KERN_SUCCESS) { MACH3_DEBUG(0, kr, ("server_exception_catcher: vm_allocate")); panic("server_exception_catcher"); } msg_buffer_2 = msg_buffer_1 + 1; request = &msg_buffer_1->hdr; reply = &msg_buffer_2->death_pill; do { kr = mach_msg(request, MACH_RCV_MSG, 0, sizeof *msg_buffer_1, server_exception_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (kr != MACH_MSG_SUCCESS) { MACH3_DEBUG(1, kr, ("server_exception_catcher: mach_msg")); panic("server_exception_catcher: receive"); } if (exc_server(request, &reply->Head)) {} else { printk("server_exception_catcher: invalid message" "(id = %d = 0x%x)\n", request->msgh_id, request->msgh_id); } panic("server_exception_catcher: what now ?"); } while (1); cthread_detach(cthread_self()); cthread_exit((void *) 0); /*NOTREACHED*/ return (void *) 0; }
void * server_thread_bootstrap( void *dummy) { struct server_thread_priv_data priv_data; void **args; int (*fn)(void *); void *arg; struct task_struct *tsk; int ret; osfmach3_jmp_buf jmp_buf; extern int sys_exit(int error_code); args = (void **) dummy; fn = (int(*)(void *)) args[0]; arg = args[1]; tsk = (struct task_struct *) args[2]; cthread_set_name(cthread_self(), "kernel thread"); server_thread_set_priv_data(cthread_self(), &priv_data); priv_data.current_task = tsk; #if 0 /* XXX ? */ tsk->osfmach3.thread->mach_thread_port = mach_thread_self(); #endif tsk->osfmach3.thread->under_server_control = TRUE; tsk->osfmach3.thread->active_on_cthread = cthread_self(); uniproc_enter(); priv_data.jmp_buf = &jmp_buf; if (osfmach3_setjmp(priv_data.jmp_buf)) { /* * The kernel thread is being terminated. */ uniproc_exit(); cthread_set_name(cthread_self(), "dead kernel thread"); cthread_detach(cthread_self()); cthread_exit((void *) 0); /*NOTREACHED*/ panic("server_thread_bootstrap: the zombie cthread walks !\n"); } kfree(args); while (current->state != TASK_RUNNING) { schedule(); /* wait until we're resumed by our parent */ } ret = (*fn)(arg); sys_exit(ret); /*NOTREACHED*/ panic("server_thread_bootstrap: the zombie kernel thread walks !\n"); }
/* * This message server catches user task exceptions. Most user exceptions * will be received on the thread exception port. This server servers * only exceptions from unknown threads or from external debuggers. * It runs in a dedicated thread. */ void * task_exception_catcher( void *arg) { struct server_thread_priv_data priv_data; kern_return_t kr; #define MSG_BUFFER_SIZE 8192 union request_msg { mach_msg_header_t hdr; mig_reply_error_t death_pill; char space[MSG_BUFFER_SIZE]; } *msg_buffer_1, *msg_buffer_2; mach_msg_header_t *request; mig_reply_error_t *reply; mach_msg_header_t *tmp; cthread_set_name(cthread_self(), "task exc catcher"); server_thread_set_priv_data(cthread_self(), &priv_data); uniproc_enter(); kr = vm_allocate(mach_task_self(), (vm_address_t *) &msg_buffer_1, 2 * sizeof *msg_buffer_1, TRUE); if (kr != KERN_SUCCESS) { MACH3_DEBUG(0, kr, ("task_exception_catcher: vm_allocate")); panic("task_exception_catcher"); } msg_buffer_2 = msg_buffer_1 + 1; request = &msg_buffer_1->hdr; reply = &msg_buffer_2->death_pill; do { uniproc_exit(); kr = mach_msg(request, MACH_RCV_MSG, 0, sizeof *msg_buffer_1, user_trap_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); if (kr != MACH_MSG_SUCCESS) { MACH3_DEBUG(1, kr, ("task_exception_catcher: mach_msg")); panic("task_exception_catcher: receive"); } uniproc_enter(); if (exc_server(request, &reply->Head)) {} else { printk("trap_exception_catcher: invalid message" "(id = %d = 0x%x)\n", request->msgh_id, request->msgh_id); } if (reply->Head.msgh_remote_port == MACH_PORT_NULL) { /* no reply port, just get another request */ continue; } if (!(reply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) && reply->RetCode == MIG_NO_REPLY) { /* deallocate reply port right */ (void) mach_port_deallocate(mach_task_self(), reply->Head.msgh_remote_port); continue; } /* Send reply to request and receive another */ uniproc_exit(); kr = mach_msg(&reply->Head, MACH_SEND_MSG, reply->Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); uniproc_enter(); if (kr != MACH_MSG_SUCCESS) { if (kr == MACH_SEND_INVALID_DEST) { /* deallocate reply port right */ /* XXX should destroy reply msg */ (void) mach_port_deallocate(mach_task_self(), reply->Head.msgh_remote_port); } else { MACH3_DEBUG(0, kr, ("mach_msg")); panic("task_exception_catcher: send"); } } tmp = request; request = (mach_msg_header_t *) reply; reply = (mig_reply_error_t *) tmp; } while (1); cthread_detach(cthread_self()); cthread_exit((void *) 0); /*NOTREACHED*/ return (void *) 0; }
void ldap_pvt_thread_exit( void *retval ) { cthread_exit( (any_t) retval ); }
void * serial_read_thread( void *arg) { struct server_thread_priv_data priv_data; kern_return_t kr; struct async_struct *info; int line, wait_loop, count; io_buf_ptr_inband_t inbuf; /* 128 chars */ mach_msg_type_number_t data_count; mach_port_t device_port; cthread_set_name(cthread_self(), "serial read"); server_thread_set_priv_data(cthread_self(), &priv_data); line = (int) arg; info = rs_table + line; uniproc_enter(); device_port = info->device_port; for (;;) { data_count = sizeof inbuf; uniproc_exit(); kr = device_read_inband(device_port, 0, /* mode */ 0, /* recnum */ sizeof inbuf, inbuf, &data_count); uniproc_enter(); if (kr == D_OUT_OF_BAND) { serial_handle_oob_event(info, device_port); continue; } else if (kr != D_SUCCESS) { /* Something happened.. simply shutdown the line.. */ if (!((info->flags & ASYNC_CALLOUT_ACTIVE) && (info->flags & ASYNC_CALLOUT_NOHUP))) queue_task_irq_off(&info->tqueue_hangup, &tq_scheduler); uniproc_exit(); cthread_detach(cthread_self()); cthread_exit((void *) 0); /* NEVER REACHED */ } if (data_count <= 0) continue; /* * Its very possible with the Power Mac * to overflow the Linux TTY buffers. * (A serial interrupt can present up to * 8K worth of data in one shot) * * The following loops attempts to give the * PPP line disc. a chance to clear the queue * out. */ for (wait_loop = 0; wait_loop < 6; wait_loop++) { /* Check to make sure the tty did not * go away.. */ if (info->tty == NULL) break; if ((info->tty->flip.count+data_count) < TTY_FLIPBUF_SIZE) break; /* Try to give another thread some time.. */ osfmach3_yield(); } if (info->tty == NULL) continue; count = MIN(TTY_FLIPBUF_SIZE + info->tty->flip.count, data_count); if (count <= 0) continue; info->last_active = jiffies; info->tty->flip.count += count; memcpy(info->tty->flip.char_buf_ptr, inbuf, count); memset(info->tty->flip.flag_buf_ptr, 0, count); info->tty->flip.flag_buf_ptr += count; info->tty->flip.char_buf_ptr += count; queue_task_irq_off(&info->tty->flip.tqueue, &tq_timer); } }