Ejemplo n.º 1
0
static int perform_x11_task() {
	if(XPending(gcore.disp) == 0)
		return 0;
  	XEvent myevent;
      	XNextEvent (gcore.disp, &myevent);
	switch (myevent.type)
	{
		case Expose:		/* Repaint window on expose */
		if (myevent.xexpose.count == 0) {
			//change_gc(myevent.xexpose.x, myevent.xexpose.y, myevent.xexpose.width, myevent.xexpose.height);
			repaint_x11();
		}
		break;
		case MappingNotify:	/* Process keyboard mapping changes: */
			XRefreshKeyboardMapping (&myevent.xmapping);
		break;
		case ConfigureNotify:
		{
			XConfigureEvent ev = myevent.xconfigure;
			if(ev.width != gcore.width || ev.height != gcore.height) {
				msg_enqueue(ENUM_ROOPKOTHA_GUI_CORE_TASK_WINDOW_TASK, ENUM_ROOPKOTHA_GUI_WINDOW_TASK_RESIZE
					, 3, gcore.wid, ev.width, ev.height);
			}
		}
		break;
#if 0
		case ResizeRequest:		/* Resize */
		{
			XResizeRequestEvent ev = myevent.xresizerequest;
			// TODO set the correct window id
			msg_enqueue(ENUM_ROOPKOTHA_GUI_CORE_TASK_WINDOW_TASK, ENUM_ROOPKOTHA_GUI_WINDOW_TASK_RESIZE, 3, 1, ev.width, ev.height);
			//set_clip(ev.window, ev.width, ev.height);
			repaint_x11();
		}
		break;
		case ButtonPress:	/* Process mouse click - output Hi! at mouse: */
		  XDrawImageString (myevent.xbutton.display, myevent.xbutton.window,
				    mygc, myevent.xbutton.x, myevent.xbutton.y, hi,
				    strlen (hi));
		  break;
#endif
		case KeyPress:		/* Process key press - quit on q: */
		{
			char text[10];
			KeySym skey = 0;
			XComposeStatus compose;
		  	int nChar = XLookupString (&myevent.xkey, text, 10, &skey, &compose);
			int i;
			int code = key_event_map(skey);
			if(code) {
				msg_enqueue(ENUM_ROOPKOTHA_GUI_CORE_TASK_WINDOW_TASK, ENUM_ROOPKOTHA_GUI_WINDOW_TASK_KEY_PRESS, 3, gcore.wid, 0, code);
			} else {
				for(i = 0; i < nChar; i++) 
					msg_enqueue(ENUM_ROOPKOTHA_GUI_CORE_TASK_WINDOW_TASK, ENUM_ROOPKOTHA_GUI_WINDOW_TASK_KEY_PRESS, 3, gcore.wid, text[i], code);
			}
		}
		break;
	}
	return 0;
}
int k_send_message(char dest_process_id, Msg_Env *msg_envelope){
	
	if (msg_envelope == NULL){
		printf("null message\n");		
		return INVALID_MESSAGE_PTR_ERROR;

	}

	if (dest_process_id < 0 || dest_process_id >9 ){        //checks validit of the p_id
		printf("invalid id\n");
		return INVALID_PID_ERROR;
	}
	msg_envelope->sender_id = msg_envelope->owner_id; 	//owner id becomes sender id
	msg_envelope->owner_id = dest_process_id;		//destination process is now the owner
	pcb *receiver = pcb_pointer(dest_process_id);		//gets the pointer to the receiving pcb
	msg_enqueue(receiver->inbox, msg_envelope);		//adds envelope to the pcbs inbox
		
	/*
	if (receiver->state == BLOCKED_ON_RECEIVE){
		receiver->state = READY;
		rpq_enqueue(receiver);				//adds process to ready process queue
	}

	//Add SENDER_PID, RECEIVER_PID, CURRENT_TIME to message trace.
	*/
	return 1;
}
Ejemplo n.º 3
0
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
 * alloc_msg_queue()									    *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
size_t alloc_msg_queue (struct msg_queue *queue, size_t len)
{
    struct msg *mp;
    size_t i;

    init_msg_queue(queue);

    if (!len)
	return 0;

    for (i = 0; i < len; i++) {
	mp = alloc_msg();
	if (mp) 
	    msg_enqueue(queue, mp);
	else
	    break;
    }
    return i;
}
Ejemplo n.º 4
0
int fill_fdset (struct msg_queue *queue, fd_set *set)
{
    struct msg_queue tmp;
    struct msg *mptr;
    int    max = 0;

    FD_ZERO(set);

    init_msg_queue(&tmp);

    while( (mptr = msg_dequeue(queue))!= NULL )
    {
	FD_SET(mptr->type.io.io_socket, set);
	max = ( max > mptr->type.io.io_socket )? max : mptr->type.io.io_socket;
	msg_enqueue(&tmp, mptr);
    }
    msgmove(queue, &tmp);

    return max;
}
Ejemplo n.º 5
0
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
 * alloc_msg_chain()									    *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
size_t alloc_msg_chain( struct msg_queue *queue, size_t len)
{
    struct msg *p_buff;
    size_t i;

    pthread_mutex_lock(&heap_msg_mutex);

    for ( i = 0; i <= len -1; i++ ) {
	p_buff = alloc_msg();
	if ( p_buff != NULL ) {
	    p_buff->p_next = NULL;
	    p_buff->mb.mbp = NULL;
	    msg_enqueue(queue, p_buff);
	}
	else
	    break;
    }
    
    pthread_mutex_unlock(&heap_msg_mutex);
    return i;
}
Ejemplo n.º 6
0
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
 * alloc_mbuff_chain()									    *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
size_t alloc_mbuff_chain( struct msg_queue *queue, size_t len)
{
    struct msg	 *p_buff;
    struct mbuff *m_buff;
    size_t i;
    /*
     * 1- Block mutex msg
     * 2- Block mutex mbuff
     * 3- Create n mbuff elements
     * 4- Create n pkbuff elements
     * 5- Unblock mutex mbuff
     * 6- Unblock mutex msg
     */
    pthread_mutex_lock(&heap_msg_mutex);
    pthread_mutex_lock(&heap_mbuff_mutex);

    for ( i = 0; i <= len-1 ; i++ ) {
	m_buff = alloc_mbuff();
	if (m_buff != NULL) {
	    p_buff = alloc_msg();
	    if (p_buff != NULL) {
		p_buff->p_next = NULL;
	        p_buff->mb.mbp = m_buff;
		msg_enqueue(queue, p_buff);
	    }
	    else {
		free_mbuff(m_buff);
		break;
	    }
	}
	else
	    break;
    }
    pthread_mutex_unlock(&heap_mbuff_mutex);
    pthread_mutex_unlock(&heap_msg_mutex);

    return i;
}
Ejemplo n.º 7
0
int k_release_msg_env(msg_envelope * rel_msg)
{
    rel_msg->sender_pid = -1;
    rel_msg->receiver_pid = -1; 
    rel_msg->msg_type = -1; 
    rel_msg->n_clock_ticks = -1; 

    if (rel_msg->msg_size != 0)
        rel_msg->msg_size = 0;
    
    int retCode = SUCCESS;
    retCode = msg_enqueue(rel_msg, free_env_Q);
    if (blocked_on_resource_Q->head != NULL)
    {
        blocked_on_resource_Q->head->process_state = READY;
        PCB *temp;
        temp = blocked_on_resource_Q_dequeue(); 
        
        retCode = rpq_enqueue(temp);
    }
    
    return retCode; //should check for error
}
Ejemplo n.º 8
0
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
 * free_msg()										    *
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void free_msg(struct msg *p)
{
    memset(p,0, sizeof(struct msg));
    msg_enqueue(&heap_msg, p);
    return;
}
Ejemplo n.º 9
0
Archivo: msg.c Proyecto: AndrewD/prex
/*
 * Send a message.
 *
 * The current thread will be blocked until any other thread
 * receives the message and calls msg_reply() for the target
 * object. When new message has been reached to the object, it
 * will be received by highest priority thread waiting for
 * that message. A thread can send a message to any object if
 * it knows the object id.
 */
int
msg_send(object_t obj, void *msg, size_t size, u_long timeout)
{
	struct msg_header *hdr;
	thread_t th;
	void *kmsg;
	int rc;

	if (!user_area(msg))
		return EFAULT;

	if (size < sizeof(struct msg_header))
		return EINVAL;

	sched_lock();

	if (!object_valid(obj)) {
		sched_unlock();
		return EINVAL;
	}
	if (obj->owner != cur_task() && !task_capable(CAP_IPC)) {
		sched_unlock();
		return EPERM;
	}
	/*
	 * A thread can not send a message when the
	 * thread is already receiving from the target
	 * object. This will obviously cause a deadlock.
	 */
	if (obj == cur_thread->recvobj) {
		sched_unlock();
		return EDEADLK;
	}
	/*
	 * Translate message address to the kernel linear
	 * address.  So that a receiver thread can access
	 * the message via kernel pointer. We can catch
	 * the page fault here.
	 */
	if ((kmsg = kmem_map(msg, size)) == NULL) {
		/* Error - no physical address for the message */
		sched_unlock();
		return EFAULT;
	}
	/*
	 * The sender ID in the message header is filled
	 * by the kernel. So, the receiver can trust it.
	 */
	hdr = (struct msg_header *)kmsg;
	hdr->task = cur_task();

	/* Save information about the message block. */
	cur_thread->msgaddr = kmsg;
	cur_thread->msgsize = size;

	/*
	 * If receiver already exists, wake it up.
	 * Highest priority thread will get this message.
	 */
	if (!queue_empty(&obj->recvq)) {
		th = msg_dequeue(&obj->recvq);
		sched_unsleep(th, 0);
	}
	/*
	 * Sleep until we get a reply message.
	 * Note: Do not touch any data in the object
	 * structure after we wakeup. This is because the
	 * target object may be deleted during we were
	 * sleeping.
	 */
	cur_thread->sendobj = obj;
	msg_enqueue(&obj->sendq, cur_thread);
	rc = sched_tsleep(&ipc_event, timeout);
	if (rc == SLP_INTR)
		queue_remove(&cur_thread->ipc_link);
	cur_thread->sendobj = NULL;

	sched_unlock();

	/*
	 * Check sleep result.
	 */
	switch (rc) {
	case SLP_BREAK:
		return EAGAIN;	/* Receiver has been terminated */
	case SLP_INVAL:
		return EINVAL;	/* Object has been deleted */
	case SLP_INTR:
		return EINTR;	/* Exception */
	case SLP_TIMEOUT:
		return ETIMEDOUT;	/* Timeout */
	default:
		/* DO NOTHING */
		break;
	}
	return 0;
}
Ejemplo n.º 10
0
int k_send_message ( int dest_process_id, msg_envelope * msg_envelope )
{
    //if (dest_process_id==0) wtf man proc A has pid 0
     //   return ERROR_INVALID_PID;

    PCB *target_PCB;
    //int n = NUM_OF_IPROC;

    int i;
    int retCode = SUCCESS;
    printf("k_send_message: Dest_process_id: %i\n", dest_process_id);
	
    for (i=0;i<NUM_TOTAL_PROC;i++) //use dest_id to look up the target process PCB pointer
    {
	if (dest_process_id == pcb_pointer_tracker[i]->process_id) 
	    target_PCB = pcb_pointer_tracker[i];
    }

    msg_queue *temp_msg_q;
    temp_msg_q= &target_PCB->msg_envelope_q;
    printf("k_send_message: Target process: %i\n",target_PCB->process_id);

    //enqueue envelope onto the message queue of the target process
    msg_envelope->sender_pid = current_process->process_id;
    msg_envelope->receiver_pid = dest_process_id;
	
    retCode = msg_enqueue(msg_envelope, temp_msg_q);
	printf("k_send_message: message send to %i by %i\n", msg_envelope->receiver_pid, msg_envelope->sender_pid);
    printf("k_send_message: check target pcb queue size: %i\n", target_PCB->msg_envelope_q.size); 

    if (target_PCB->msg_envelope_q.head==NULL)
	printf("send failed: msg_envelope_q is null\n");

	printf("k_send_message:target process %i msg q size: %i\n", target_PCB->process_id, target_PCB->msg_envelope_q.size); 

    if(target_PCB->process_state == BLOCKED_ON_RECEIVE)
    {
		target_PCB->process_state = READY;
		printf("k_send_message:eEnquing process %i to rpq\n", target_PCB->process_id); 
		retCode = rpq_enqueue(target_PCB);//enqueue blocked process to ready queue;
    }

	//Record send on the trace buffer
	if (send_tr_buf->index == 15) {
		//If the trace buffer is full
		int i;
		//Shift the stored data by 1 unit
		for (i = 0; i <send_tr_buf->index; i++){
			send_tr_buf->send_trace_buffer_array[i].sender_pid = send_tr_buf->send_trace_buffer_array[i+1].sender_pid;
			send_tr_buf->send_trace_buffer_array[i].receiver_pid = send_tr_buf->send_trace_buffer_array[i+1].receiver_pid;
			send_tr_buf->send_trace_buffer_array[i].time = send_tr_buf->send_trace_buffer_array[i+1].time;
		}

		send_tr_buf->send_trace_buffer_array[15].sender_pid = msg_envelope->sender_pid;
		send_tr_buf->send_trace_buffer_array[15].receiver_pid = msg_envelope->receiver_pid;
		send_tr_buf->send_trace_buffer_array[15].time = kernel_clock;
	} else {
		send_tr_buf->index++;
		send_tr_buf->send_trace_buffer_array[send_tr_buf->index].sender_pid = msg_envelope->sender_pid;
		send_tr_buf->send_trace_buffer_array[send_tr_buf->index].receiver_pid = msg_envelope->receiver_pid;
		send_tr_buf->send_trace_buffer_array[send_tr_buf->index].time = kernel_clock;
	}   

	return SUCCESS;
}
Ejemplo n.º 11
0
Archivo: msg.c Proyecto: uiv/Lerdu
/*
 * Send a message.
 *
 * The current thread will be blocked until any other thread
 * receives and reply the message.  A thread can send a
 * message to any object if it knows the object id.
 */
int
msg_send(object_t obj, void *msg, size_t size)
{
	struct msg_header *hdr;
	thread_t t;
	void *kmsg;
	int rc;

	if (!user_area(msg))
		return EFAULT;

	if (size < sizeof(struct msg_header))
		return EINVAL;

	sched_lock();

	if (!object_valid(obj)) {
		sched_unlock();
		return EINVAL;
	}
	/*
	 * A thread can not send a message when it is
	 * already receiving from the target object.
	 * It will obviously cause a deadlock.
	 */
	if (obj == curthread->recvobj) {
		sched_unlock();
		return EDEADLK;
	}
	/*
	 * Translate message address to the kernel linear
	 * address.  So that a receiver thread can access
	 * the message via kernel pointer. We can catch
	 * the page fault here.
	 */
	if ((kmsg = kmem_map(msg, size)) == NULL) {
		sched_unlock();
		return EFAULT;
	}
	curthread->msgaddr = kmsg;
	curthread->msgsize = size;

	/*
	 * The sender ID is filled in the message header
	 * by the kernel. So, the receiver can trust it.
	 */
	hdr = (struct msg_header *)kmsg;
	hdr->task = curtask;

	/*
	 * If receiver already exists, wake it up.
	 * The highest priority thread can get the message.
	 */
	if (!queue_empty(&obj->recvq)) {
		t = msg_dequeue(&obj->recvq);
		sched_unsleep(t, 0);
	}
	/*
	 * Sleep until we get a reply message.
	 * Note: Do not touch any data in the object
	 * structure after we wakeup. This is because the
	 * target object may be deleted while we are sleeping.
	 */
	curthread->sendobj = obj;
	msg_enqueue(&obj->sendq, curthread);
	rc = sched_sleep(&ipc_event);
	if (rc == SLP_INTR)
		queue_remove(&curthread->ipc_link);
	curthread->sendobj = NULL;

	sched_unlock();

	/*
	 * Check sleep result.
	 */
	switch (rc) {
	case SLP_BREAK:
		return EAGAIN;	/* Receiver has been terminated */
	case SLP_INVAL:
		return EINVAL;	/* Object has been deleted */
	case SLP_INTR:
		return EINTR;	/* Exception */
	default:
		/* DO NOTHING */
		break;
	}
	return 0;
}
Ejemplo n.º 12
0
Archivo: msg.c Proyecto: uiv/Lerdu
/*
 * Receive a message.
 *
 * A thread can receive a message from the object which was
 * created by any thread belongs to same task. If the message
 * has not reached yet, it blocks until any message comes in.
 *
 * The size argument specifies the "maximum" size of the message
 * buffer to receive. If the sent message is larger than this
 * size, the kernel will automatically clip the message to this
 * maximum buffer size.
 *
 * When a message is received, the sender thread is removed from
 * object's send queue. So, another thread can receive the
 * subsequent message from that object. This is important for
 * the multi-thread server which must receive multiple messages
 * simultaneously.
 */
int
msg_receive(object_t obj, void *msg, size_t size)
{
	thread_t t;
	size_t len;
	int rc, error = 0;

	if (!user_area(msg))
		return EFAULT;

	sched_lock();

	if (!object_valid(obj)) {
		sched_unlock();
		return EINVAL;
	}
	if (obj->owner != curtask) {
		sched_unlock();
		return EACCES;
	}
	/*
	 * Check if this thread finished previous receive
	 * operation.  A thread can not receive different
	 * messages at once.
	 */
	if (curthread->recvobj) {
		sched_unlock();
		return EBUSY;
	}
	curthread->recvobj = obj;

	/*
	 * If no message exists, wait until message arrives.
	 */
	while (queue_empty(&obj->sendq)) {
		/*
		 * Block until someone sends a message.
		 */
		msg_enqueue(&obj->recvq, curthread);
		rc = sched_sleep(&ipc_event);
		if (rc != 0) {
			/*
			 * Receive is failed due to some reasons.
			 */
			switch (rc) {
			case SLP_INVAL:
				error = EINVAL;	/* Object has been deleted */
				break;
			case SLP_INTR:
				queue_remove(&curthread->ipc_link);
				error = EINTR;	/* Got exception */
				break;
			default:
				panic("msg_receive");
				break;
			}
			curthread->recvobj = NULL;
			sched_unlock();
			return error;
		}

		/*
		 * Check the existence of the sender thread again.
		 * Even if this thread is woken by the sender thread,
		 * the message may be received by another thread.
		 * This may happen when another high priority thread
		 * becomes runnable before we receive the message.
		 */
	}

	t = msg_dequeue(&obj->sendq);

	/*
	 * Copy out the message to the user-space.
	 */
	len = MIN(size, t->msgsize);
	if (len > 0) {
		if (copyout(t->msgaddr, msg, len)) {
			msg_enqueue(&obj->sendq, t);
			curthread->recvobj = NULL;
			sched_unlock();
			return EFAULT;
		}
	}
	/*
	 * Detach the message from the target object.
	 */
	curthread->sender = t;
	t->receiver = curthread;

	sched_unlock();
	return error;
}
Ejemplo n.º 13
0
Archivo: mqtt.c Proyecto: pvvx/EspLua
void mqtt_socket_timer(void *arg)
{
  NODE_DBG("enter mqtt_socket_timer.\n");
  lmqtt_userdata *mud = (lmqtt_userdata*) arg;

  if(mud == NULL)
    return;
  if(mud->pesp_conn == NULL){
    NODE_DBG("mud->pesp_conn is NULL.\n");
    os_timer_disarm(&mud->mqttTimer);
    return;
  }

  NODE_DBG("timer, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q)));
  if(mud->event_timeout > 0){
    NODE_DBG("event_timeout: %d.\n", mud->event_timeout);
  	mud->event_timeout --;
    if(mud->event_timeout > 0){
      return;
    } else {
      NODE_DBG("event timeout. \n");
      if(mud->connState == MQTT_DATA)
        msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
      // should remove the head of the queue and re-send with DUP = 1
      // Not implemented yet.
    }
  }

  if(mud->connState == MQTT_INIT){ // socket connect time out.
    NODE_DBG("Can not connect to broker.\n");
    // Never goes here.
  } else if(mud->connState == MQTT_CONNECT_SENDING){ // MQTT_CONNECT send time out.
    NODE_DBG("sSend MQTT_CONNECT failed.\n");
    mud->connState = MQTT_INIT;
    if(mud->secure)
      espconn_secure_disconnect(mud->pesp_conn);
    else 
      espconn_disconnect(mud->pesp_conn);
    mud->keep_alive_tick = 0; // not need count anymore
  } else if(mud->connState == MQTT_CONNECT_SENT){ // wait for CONACK time out.
    NODE_DBG("MQTT_CONNECT failed.\n");
  } else if(mud->connState == MQTT_DATA){
    msg_queue_t *pending_msg = msg_peek(&(mud->mqtt_state.pending_msg_q));
    if(pending_msg){
      mud->event_timeout = MQTT_SEND_TIMEOUT;
      if(mud->secure)
        espconn_secure_sent(mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length);
      else
        espconn_sent(mud->pesp_conn, pending_msg->msg.data, pending_msg->msg.length);
      mud->keep_alive_tick = 0;
      NODE_DBG("id: %d - qos: %d, length: %d\n", pending_msg->msg_id, pending_msg->publish_qos, pending_msg->msg.length);
    } else {
      // no queued event.
      mud->keep_alive_tick ++;
      if(mud->keep_alive_tick > mud->mqtt_state.connect_info->keepalive){
        mud->event_timeout = MQTT_SEND_TIMEOUT;
        uint8_t temp_buffer[MQTT_BUF_SIZE];
        mqtt_msg_init(&mud->mqtt_state.mqtt_connection, temp_buffer, MQTT_BUF_SIZE);
        NODE_DBG("\r\nMQTT: Send keepalive packet\r\n");
        mqtt_message_t* temp_msg = mqtt_msg_pingreq(&mud->mqtt_state.mqtt_connection);
        msg_queue_t *node = msg_enqueue( &(mud->mqtt_state.pending_msg_q), temp_msg, 
                            0, MQTT_MSG_TYPE_PINGREQ, (int)mqtt_get_qos(temp_msg->data) );
        // only one message in queue, send immediately.
        if(mud->secure)
          espconn_secure_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
        else
          espconn_sent(mud->pesp_conn, temp_msg->data, temp_msg->length);
        mud->keep_alive_tick = 0;
      }
    }
  }
  NODE_DBG("leave mqtt_socket_timer.\n");
}
Ejemplo n.º 14
0
Archivo: mqtt.c Proyecto: pvvx/EspLua
static void mqtt_socket_received(void *arg, char *pdata, unsigned short len)
{
  NODE_DBG("enter mqtt_socket_received.\n");

  uint8_t msg_type;
  uint8_t msg_qos;
  uint16_t msg_id;
  msg_queue_t *node = NULL;
  int length = (int)len;
  // uint8_t in_buffer[MQTT_BUF_SIZE];
  uint8_t *in_buffer = (uint8_t *)pdata;

  struct espconn *pesp_conn = arg;
  if(pesp_conn == NULL)
    return;
  lmqtt_userdata *mud = (lmqtt_userdata *)pesp_conn->reverse;
  if(mud == NULL)
    return;

READPACKET:
  if(length > MQTT_BUF_SIZE || length <= 0)
	  return;

  // c_memcpy(in_buffer, pdata, length);
  uint8_t temp_buffer[MQTT_BUF_SIZE];
  mqtt_msg_init(&mud->mqtt_state.mqtt_connection, temp_buffer, MQTT_BUF_SIZE);
  mqtt_message_t *temp_msg = NULL;
  switch(mud->connState){
    case MQTT_CONNECT_SENDING:
    case MQTT_CONNECT_SENT:
      if(mqtt_get_type(in_buffer) != MQTT_MSG_TYPE_CONNACK){
        NODE_DBG("MQTT: Invalid packet\r\n");
        mud->connState = MQTT_INIT;
        if(mud->secure)
          espconn_secure_disconnect(pesp_conn);
        else
          espconn_disconnect(pesp_conn);
      } else {
        mud->connState = MQTT_DATA;
        NODE_DBG("MQTT: Connected\r\n");
        if(mud->cb_connect_ref == LUA_NOREF)
          break;
        if(mud->self_ref == LUA_NOREF)
          break;
        if(mud->L == NULL)
          break;
        lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_connect_ref);
        lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref);  // pass the userdata(client) to callback func in lua
        lua_call(mud->L, 1, 0);
        break;
      }
      break;

    case MQTT_DATA:
      mud->mqtt_state.message_length_read = length;
      mud->mqtt_state.message_length = mqtt_get_total_length(in_buffer, mud->mqtt_state.message_length_read);
      msg_type = mqtt_get_type(in_buffer);
      msg_qos = mqtt_get_qos(in_buffer);
      msg_id = mqtt_get_id(in_buffer, mud->mqtt_state.message_length);

      msg_queue_t *pending_msg = msg_peek(&(mud->mqtt_state.pending_msg_q));

      NODE_DBG("MQTT_DATA: type: %d, qos: %d, msg_id: %d, pending_id: %d\r\n",
            msg_type,
            msg_qos,
            msg_id,
            (pending_msg)?pending_msg->msg_id:0);
      switch(msg_type)
      {
        case MQTT_MSG_TYPE_SUBACK:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_SUBSCRIBE && pending_msg->msg_id == msg_id){
            NODE_DBG("MQTT: Subscribe successful\r\n");
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
            if (mud->cb_suback_ref == LUA_NOREF)
              break;
            if (mud->self_ref == LUA_NOREF)
              break;
            if(mud->L == NULL)
              break;
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_suback_ref);
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref);
            lua_call(mud->L, 1, 0);
          }
          break;
        case MQTT_MSG_TYPE_UNSUBACK:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_UNSUBSCRIBE && pending_msg->msg_id == msg_id){
            NODE_DBG("MQTT: UnSubscribe successful\r\n");
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
          }
          break;
        case MQTT_MSG_TYPE_PUBLISH:
          if(msg_qos == 1){
            temp_msg = mqtt_msg_puback(&mud->mqtt_state.mqtt_connection, msg_id);
            node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PUBACK, (int)mqtt_get_qos(temp_msg->data) );
          }
          else if(msg_qos == 2){
            temp_msg = mqtt_msg_pubrec(&mud->mqtt_state.mqtt_connection, msg_id);
            node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PUBREC, (int)mqtt_get_qos(temp_msg->data) );
          }
          if(msg_qos == 1 || msg_qos == 2){
            NODE_DBG("MQTT: Queue response QoS: %d\r\n", msg_qos);
          }
          deliver_publish(mud, in_buffer, mud->mqtt_state.message_length);
          break;
        case MQTT_MSG_TYPE_PUBACK:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg->msg_id == msg_id){
            NODE_DBG("MQTT: Publish with QoS = 1 successful\r\n");
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
            if(mud->cb_puback_ref == LUA_NOREF)
              break;
            if(mud->self_ref == LUA_NOREF)
              break;
            if(mud->L == NULL)
              break;
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_puback_ref);
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref);  // pass the userdata to callback func in lua
            lua_call(mud->L, 1, 0);
          }

          break;
        case MQTT_MSG_TYPE_PUBREC:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBLISH && pending_msg->msg_id == msg_id){
            NODE_DBG("MQTT: Publish  with QoS = 2 Received PUBREC\r\n"); 
            // Note: actrually, should not destroy the msg until PUBCOMP is received.
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
            temp_msg = mqtt_msg_pubrel(&mud->mqtt_state.mqtt_connection, msg_id);
            node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PUBREL, (int)mqtt_get_qos(temp_msg->data) );
            NODE_DBG("MQTT: Response PUBREL\r\n");
          }
          break;
        case MQTT_MSG_TYPE_PUBREL:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBREC && pending_msg->msg_id == msg_id){
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
            temp_msg = mqtt_msg_pubcomp(&mud->mqtt_state.mqtt_connection, msg_id);
            node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PUBCOMP, (int)mqtt_get_qos(temp_msg->data) );
            NODE_DBG("MQTT: Response PUBCOMP\r\n");
          }
          break;
        case MQTT_MSG_TYPE_PUBCOMP:
          if(pending_msg && pending_msg->msg_type == MQTT_MSG_TYPE_PUBREL && pending_msg->msg_id == msg_id){
            NODE_DBG("MQTT: Publish  with QoS = 2 successful\r\n");
            msg_destroy(msg_dequeue(&(mud->mqtt_state.pending_msg_q)));
            if(mud->cb_puback_ref == LUA_NOREF)
              break;
            if(mud->self_ref == LUA_NOREF)
              break;
            if(mud->L == NULL)
              break;
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->cb_puback_ref);
            lua_rawgeti(mud->L, LUA_REGISTRYINDEX, mud->self_ref);  // pass the userdata to callback func in lua
            lua_call(mud->L, 1, 0);
          }
          break;
        case MQTT_MSG_TYPE_PINGREQ:
            temp_msg = mqtt_msg_pingresp(&mud->mqtt_state.mqtt_connection);
            node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PINGRESP, (int)mqtt_get_qos(temp_msg->data) );
            NODE_DBG("MQTT: Response PINGRESP\r\n");
          break;
        case MQTT_MSG_TYPE_PINGRESP:
          // Ignore
          NODE_DBG("MQTT: PINGRESP received\r\n");
          break;
      }
      // NOTE: this is done down here and not in the switch case above
      // because the PSOCK_READBUF_LEN() won't work inside a switch
      // statement due to the way protothreads resume.
      if(msg_type == MQTT_MSG_TYPE_PUBLISH)
      {

        length = mud->mqtt_state.message_length_read;

        if(mud->mqtt_state.message_length < mud->mqtt_state.message_length_read)
				{
					length -= mud->mqtt_state.message_length;
					in_buffer += mud->mqtt_state.message_length;

					NODE_DBG("Get another published message\r\n");
					goto READPACKET;
				}
      }
      break;
  }

  if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
    mud->event_timeout = MQTT_SEND_TIMEOUT;
    NODE_DBG("Sent: %d\n", node->msg.length);
    if( mud->secure )
      espconn_secure_sent( pesp_conn, node->msg.data, node->msg.length );
    else
      espconn_sent( pesp_conn, node->msg.data, node->msg.length );
  }
  mud->keep_alive_tick = 0;
  NODE_DBG("receive, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q)));
  NODE_DBG("leave mqtt_socket_received.\n");
  return;
}
Ejemplo n.º 15
0
Archivo: mqtt.c Proyecto: pvvx/EspLua
// Lua: bool = mqtt:publish( topic, payload, qos, retain, function() )
static int mqtt_socket_publish( lua_State* L )
{
  NODE_DBG("enter mqtt_socket_publish.\n");
  struct espconn *pesp_conn = NULL;
  lmqtt_userdata *mud;
  size_t l;
  uint8_t stack = 1;
  uint16_t msg_id = 0;
  mud = (lmqtt_userdata *)luaL_checkudata(L, stack, "mqtt.socket");
  luaL_argcheck(L, mud, stack, "mqtt.socket expected");
  stack++;
  if(mud==NULL){
    NODE_DBG("userdata is nil.\n");
    lua_pushboolean(L, 0);
    return 1;
  }

  if(mud->pesp_conn == NULL){
    NODE_DBG("mud->pesp_conn is NULL.\n");
    lua_pushboolean(L, 0);
    return 1;
  }

  if(!mud->connected){
    luaL_error( L, "not connected" );
    lua_pushboolean(L, 0);
    return 1;
  }

  const char *topic = luaL_checklstring( L, stack, &l );
  stack ++;
  if (topic == NULL){
    luaL_error( L, "need topic" );
    lua_pushboolean(L, 0);
    return 1;
  }

  const char *payload = luaL_checklstring( L, stack, &l );
  stack ++;
  uint8_t qos = luaL_checkinteger( L, stack);
  stack ++;
  uint8_t retain = luaL_checkinteger( L, stack);
  stack ++;

  uint8_t temp_buffer[MQTT_BUF_SIZE];
  mqtt_msg_init(&mud->mqtt_state.mqtt_connection, temp_buffer, MQTT_BUF_SIZE);
  mqtt_message_t *temp_msg = mqtt_msg_publish(&mud->mqtt_state.mqtt_connection,
                       topic, payload, l,
                       qos, retain,
                       &msg_id);

  if (lua_type(L, stack) == LUA_TFUNCTION || lua_type(L, stack) == LUA_TLIGHTFUNCTION){
    lua_pushvalue(L, stack);  // copy argument (func) to the top of stack
    if(mud->cb_puback_ref != LUA_NOREF)
      luaL_unref(L, LUA_REGISTRYINDEX, mud->cb_puback_ref);
    mud->cb_puback_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  }

  msg_queue_t *node = msg_enqueue(&(mud->mqtt_state.pending_msg_q), temp_msg, 
                      msg_id, MQTT_MSG_TYPE_PUBLISH, (int)qos );

  if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
    mud->event_timeout = MQTT_SEND_TIMEOUT;
    NODE_DBG("Sent: %d\n", node->msg.length);
    if( mud->secure )
      espconn_secure_sent( mud->pesp_conn, node->msg.data, node->msg.length );
    else
      espconn_sent( mud->pesp_conn, node->msg.data, node->msg.length );
    mud->keep_alive_tick = 0;
  }

  if(!node){
    lua_pushboolean(L, 0);
  } else {
    lua_pushboolean(L, 1);  // enqueued succeed.
  }

  NODE_DBG("publish, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q)));
  NODE_DBG("leave mqtt_socket_publish.\n");
  return 1;
}
Ejemplo n.º 16
0
Archivo: mqtt.c Proyecto: pvvx/EspLua
// Lua: bool = mqtt:subscribe(topic, qos, function())
static int mqtt_socket_subscribe( lua_State* L ) {
	NODE_DBG("enter mqtt_socket_subscribe.\n");

	uint8_t stack = 1, qos = 0;
  uint16_t msg_id = 0;
	const char *topic;
	size_t il;
	lmqtt_userdata *mud;

	mud = (lmqtt_userdata *) luaL_checkudata( L, stack, "mqtt.socket" );
	luaL_argcheck( L, mud, stack, "mqtt.socket expected" );
	stack++;

  if(mud==NULL){
    NODE_DBG("userdata is nil.\n");
    lua_pushboolean(L, 0);
    return 1;
  }

  if(mud->pesp_conn == NULL){
    NODE_DBG("mud->pesp_conn is NULL.\n");
    lua_pushboolean(L, 0);
    return 1;
  }

	if(!mud->connected){
		luaL_error( L, "not connected" );
    lua_pushboolean(L, 0);
    return 1;
  }

  uint8_t temp_buffer[MQTT_BUF_SIZE];
  mqtt_msg_init(&mud->mqtt_state.mqtt_connection, temp_buffer, MQTT_BUF_SIZE);
  mqtt_message_t *temp_msg = NULL;

	if( lua_istable( L, stack ) ) {
		NODE_DBG("subscribe table\n");
		lua_pushnil( L ); /* first key */

    uint8_t temp_buf[MQTT_BUF_SIZE];
    uint32_t temp_pos = 0;

		while( lua_next( L, stack ) != 0 ) {
			topic = luaL_checkstring( L, -2 );
			qos = luaL_checkinteger( L, -1 );

			temp_msg = mqtt_msg_subscribe( &mud->mqtt_state.mqtt_connection, topic, qos, &msg_id );
			NODE_DBG("topic: %s - qos: %d, length: %d\n", topic, qos, temp_msg->length);

      if (temp_pos + temp_msg->length > MQTT_BUF_SIZE){
        lua_pop(L, 1);
        break;  // too long message for the outbuffer.
      }
      c_memcpy( temp_buf + temp_pos, temp_msg->data, temp_msg->length );
      temp_pos += temp_msg->length;

			lua_pop( L, 1 );
		}

    if (temp_pos == 0){
      luaL_error( L, "invalid data" );
      lua_pushboolean(L, 0);
      return 1;
    }

    c_memcpy( temp_buffer, temp_buf, temp_pos );
		temp_msg->data = temp_buffer;
		temp_msg->length = temp_pos;
		stack++;
	} else {
		NODE_DBG("subscribe string\n");
		topic = luaL_checklstring( L, stack, &il );
		stack++;
		if( topic == NULL ){
			luaL_error( L, "need topic name" );
      lua_pushboolean(L, 0);
      return 1;
    }
		qos = luaL_checkinteger( L, stack );
		temp_msg = mqtt_msg_subscribe( &mud->mqtt_state.mqtt_connection, topic, qos, &msg_id );
		stack++;
	}

  if( lua_type( L, stack ) == LUA_TFUNCTION || lua_type( L, stack ) == LUA_TLIGHTFUNCTION ) {    // TODO: this will overwrite the previous one.
    lua_pushvalue( L, stack );  // copy argument (func) to the top of stack
    if( mud->cb_suback_ref != LUA_NOREF )
      luaL_unref( L, LUA_REGISTRYINDEX, mud->cb_suback_ref );
    mud->cb_suback_ref = luaL_ref( L, LUA_REGISTRYINDEX );
  }

  msg_queue_t *node = msg_enqueue( &(mud->mqtt_state.pending_msg_q), temp_msg, 
                            msg_id, MQTT_MSG_TYPE_SUBSCRIBE, (int)mqtt_get_qos(temp_msg->data) );

  NODE_DBG("topic: %s - id: %d - qos: %d, length: %d\n", topic, node->msg_id, node->publish_qos, node->msg.length);

  if(node && (1==msg_size(&(mud->mqtt_state.pending_msg_q))) && mud->event_timeout == 0){
  	mud->event_timeout = MQTT_SEND_TIMEOUT;
  	NODE_DBG("Sent: %d\n", node->msg.length);
  	if( mud->secure )
  		espconn_secure_sent( mud->pesp_conn, node->msg.data, node->msg.length );
  	else
  		espconn_sent( mud->pesp_conn, node->msg.data, node->msg.length );
    mud->keep_alive_tick = 0;
  }

  if(!node){
    lua_pushboolean(L, 0);
  } else {
    lua_pushboolean(L, 1);  // enqueued succeed.
  }
  NODE_DBG("subscribe, queue size: %d\n", msg_size(&(mud->mqtt_state.pending_msg_q)));
  NODE_DBG("leave mqtt_socket_subscribe.\n");
	return 1;
}
Ejemplo n.º 17
0
void *dataio (void *arg)
{
    struct msg_queue wpenq;		/* Pendientes de escritura */
    struct msg_queue rpenq;		/* Pendientes de lectura   */
    struct msg_queue to_krn;
    struct msg_queue tmp;
    struct mb_queue  no_sent;
    struct itc_event_info ieinfo;
    struct msg	     *mptr;
    ssize_t io_ret;
    int max, ret;
    fd_set wset, rset;
    char   *where;

    arg = NULL;

    itc_block_signal();

    init_msg_queue(&wpenq);
    init_msg_queue(&rpenq);

    while (1)
    {
	FD_ZERO(&wset);
	FD_ZERO(&rset);
	/*
         * Add itc file descriptor
         */
	FD_SET(itc_event, &rset);
	max = itc_event;

	/*
	 * Add all sockets scaning read events 
	 */
	
	ret = fill_fdset(&rpenq, &rset);
	max = ( max > ret ) ? max : ret;
	/*
         * Add all sockets scaning write envents
         */
	ret = fill_fdset(&wpenq, &wset);
	max = ( max > ret ) ? max : ret;
	
	ret = select_nosignal(max+1, &rset, &wset, NULL, NULL);
	if (ret == -1)
	{
	    where = "select_nosignal()";
	    goto panic;
	}
	init_msg_queue(&tmp);
	init_msg_queue(&to_krn);

	while ((mptr = msg_dequeue(&wpenq)) != NULL)
	{
	    if (FD_ISSET(mptr->type.io.io_socket, &wset)) {
		io_ret = senddata(mptr->type.io.io_socket,
				 &mptr->mb.mbq,
				 &no_sent, DISCARD_TRUE);
		
		if (io_ret > 0 && no_sent.size == 0) {
		    mptr->type.io.io_opt = IO_OPT_WRITE;
		    mptr->type.io.io_ret = IO_RET_SUCCESS;
		    mptr->type.io.io_errno   = 0;
		    mptr->type.io.io_rep_len += io_ret;

		    mptr->msg_type = MSG_IO_REPLY;

		    msg_enqueue(&to_krn, mptr);
		}
		else if ( io_ret == -1 ) {
		    mptr->type.io.io_opt = IO_OPT_WRITE;
		    mptr->type.io.io_ret = IO_RET_FAILURE;
		    mptr->type.io.io_errno = errno;
		
		    mptr->msg_type = MSG_IO_REPLY;
		    mbuffmove(&(mptr->mb.mbq), &no_sent);
		    msg_enqueue(&to_krn, mptr);
		}
		else {
		    mptr->type.io.io_rep_len += io_ret;
		    mbuffmove(&(mptr->mb.mbq), &no_sent);
		    msg_enqueue(&tmp, mptr);
		}
	    }
	    else
		msg_enqueue(&tmp, mptr);
	}
	msgmove(&wpenq, &tmp);

	init_msg_queue(&tmp);

	while ((mptr = msg_dequeue(&rpenq)) != NULL)
	{
	    if (FD_ISSET(mptr->type.io.io_socket, &rset)) {
		io_ret = recvdata(mptr->type.io.io_socket,
				 &(mptr->mb.mbq),
				 mptr->type.io.io_req_len, mptr->type.io.io_chunk_size);
		
		if (io_ret > 0) {
		    mptr->type.io.io_opt = IO_OPT_READ;
		    mptr->type.io.io_ret = IO_RET_SUCCESS;
		    mptr->type.io.io_errno   = 0;
		    mptr->type.io.io_rep_len = io_ret;

		    mptr->msg_type = MSG_IO_REPLY;

		    msg_enqueue(&to_krn, mptr);
		}
		else if ( io_ret == -1 ) {
		    mptr->type.io.io_opt = IO_OPT_READ;
		    mptr->type.io.io_ret = IO_RET_FAILURE;
		    mptr->type.io.io_errno = errno;
		    mptr->msg_type = MSG_IO_REPLY;
		    msg_enqueue(&to_krn, mptr);
		}
		else {
		    msg_enqueue(&tmp, mptr);
		}
	    }
	    else
		msg_enqueue(&tmp, mptr);
	}
	msgmove(&rpenq, &tmp);

	init_msg_queue(&tmp);

	/*
	 * Look for new request
	 */
	if (FD_ISSET(itc_event, &rset)) 
	{
	    ret = itc_read_event(itc_event, &ieinfo);
	    if (ret == -1)
	    {
		where = "itc_read_event()";
		goto panic;
	    }

	    if (ieinfo.src != KERNEL_LAYER_THREAD)
	    {
		where = "[itc wrong src]";
		goto panic;
	    }
	    
	    itc_readfrom(KERNEL_LAYER_THREAD,
		         &tmp,
			 0);

	    while( (mptr = msg_dequeue(&tmp)) != NULL)
	    {
		if (mptr->msg_type != MSG_IO_REQUEST)
		    /* Drop silently */
		    continue;
		mptr->type.io.io_ret     = 0;
		mptr->type.io.io_errno   = 0;
		mptr->type.io.io_rep_len = 0;
		if (mptr->type.io.io_opt == IO_OPT_READ)
		    msg_enqueue(&rpenq, mptr);
		if (mptr->type.io.io_opt == IO_OPT_WRITE)
		    msg_enqueue(&wpenq, mptr);
	    }
	}

	/*
         * Send the reply to the kernel
	 */
	if (to_krn.size != 0)
	    itc_writeto(KERNEL_LAYER_THREAD,
			&to_krn,
			0);
    }

panic:
    PANIC(errno,"DATAIO_LAYER_THREAD",where);
    return NULL;
}
Ejemplo n.º 18
0
Archivo: msg.c Proyecto: AndrewD/prex
/*
 * Receive a message.
 *
 * A thread can receive a message from the object which was
 * created by any thread belongs to same task. If the message
 * has not arrived yet, it blocks until any message comes in.
 *
 * The size argument specifies the "maximum" size of the message
 * buffer to receive. If the sent message is larger than this
 * size, the kernel will automatically clip the message to the
 * receive buffer size.
 *
 * When message is received, the sender thread is removed from
 * object's send queue. So, another thread can receive the
 * subsequent message from that object. This is important for
 * the multi-thread server which receives some messages
 * simultaneously.
 */
int
msg_receive(object_t obj, void *msg, size_t size, u_long timeout)
{
	thread_t th;
	size_t len;
	int rc, err = 0;

	if (!user_area(msg))
		return EFAULT;

	sched_lock();

	if (!object_valid(obj)) {
		err = EINVAL;
		goto out;
	}
	if (obj->owner != cur_task()) {
		err = EACCES;
		goto out;
	}
	/*
	 * Check if this thread finished previous receive
	 * operation.  A thread can not receive different
	 * messages at once.
	 */
	if (cur_thread->recvobj) {
		err = EBUSY;
		goto out;
	}
	cur_thread->recvobj = obj;

	/*
	 * If no message exists, wait until message arrives.
	 */
	while (queue_empty(&obj->sendq)) {
		/*
		 * Block until someone sends the message.
		 */
		msg_enqueue(&obj->recvq, cur_thread);
		rc = sched_tsleep(&ipc_event, timeout);
		if (rc != 0) {
			/*
			 * Receive is failed due to some reasons.
			 */
			switch (rc) {
			case SLP_INVAL:
				err = EINVAL;	/* Object has been deleted */
				break;
			case SLP_INTR:
				queue_remove(&cur_thread->ipc_link);
				err = EINTR;	/* Got exception */
				break;
			case SLP_TIMEOUT:
				err = ETIMEDOUT;	/* Timeout */
				break;
			default:
				panic("msg_receive");
				break;
			}
			cur_thread->recvobj = NULL;
			goto out;
		}

		/*
		 * Even if this thread is woken by the sender thread,
		 * the message may be received by another thread
		 * before this thread runs. This can occur when
		 * higher priority thread becomes runnable at that
		 * time. So, it is necessary to check the existence
		 * of the sender, again.
		 */
	}

	th = msg_dequeue(&obj->sendq);

	/*
	 * Copy out the message to the user-space.
	 * The smaller buffer size is used as copy length
	 * between sender and receiver thread.
	 */
	len = min(size, th->msgsize);
	if (len > 0) {
		if (umem_copyout(th->msgaddr, msg, len)) {
			msg_enqueue(&obj->sendq, th);
			cur_thread->recvobj = NULL;
			err = EFAULT;
			goto out;
		}
	}
	/*
	 * Detach the message from the target object.
	 */
	cur_thread->sender = th;
	th->receiver = cur_thread;
 out:
	sched_unlock();
	return err;
}