Пример #1
0
status_t send_msg_x( port_id hPort, uint32 nCode, const void *pBuffer, int nSize, bigtime_t nTimeOut )
{
	MsgPort_s *psPort;
	MessageNode_s *psNode;
	int nError;

	psNode = kmalloc( sizeof( MessageNode_s ) + nSize, MEMF_KERNEL | MEMF_LOCKED | MEMF_OKTOFAIL );

	if ( psNode == NULL )
	{
		printk( "Error: send_msg_x() failed to alloc message buffer\n" );
		return ( -ENOMEM );
	}

	psNode->mn_psNext = NULL;
	psNode->mn_nCode = nCode;

	if ( NULL != pBuffer )
	{
		memcpy( psNode + 1, pBuffer, nSize );
		psNode->mn_nSize = nSize;
	}
	else
	{
		psNode->mn_nSize = 0;
	}

	lock_mutex( g_hPortListSema, true );

	psPort = get_port_from_handle( hPort );

	if ( psPort == NULL )
	{
		printk( "Error: send_msg_x() attempt to send to invalid port %d\n", hPort );
		nError = -EINVAL;
		goto error;
	}

	if ( NULL == psPort->mp_psFirstMsg )
	{
		psPort->mp_psFirstMsg = psNode;
		psPort->mp_psLastMsg = psNode;
	}
	else
	{
		kassertw( NULL != psPort->mp_psLastMsg );

		psPort->mp_psLastMsg->mn_psNext = psNode;
		psPort->mp_psLastMsg = psNode;
	}
	psPort->mp_nCount++;
	UNLOCK( psPort->mp_hSyncSema );
	unlock_mutex( g_hPortListSema );

	return ( 0 );
      error:
	kfree( psNode );
	unlock_mutex( g_hPortListSema );
	return ( nError );
}
Пример #2
0
static VALUE
rb_queue_pop(int argc, VALUE *argv, VALUE self)
{
    Queue *queue;
    int should_block;
    VALUE result;
    Data_Get_Struct(self, Queue, queue);

    if (argc == 0) {
        should_block = 1;
    } else if (argc == 1) {
        should_block = !RTEST(argv[0]);
    } else {
        rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
    }

    lock_mutex(&queue->mutex);
    if (!queue->values.entries && !should_block) {
        unlock_mutex(&queue->mutex);
        rb_raise(private_eThreadError, "queue empty");
    }

    while (!queue->values.entries) {
        wait_condvar(&queue->value_available, &queue->mutex);
    }

    result = shift_list(&queue->values);
    if (queue->capacity && queue->values.size < queue->capacity) {
        signal_condvar(&queue->space_available);
    }
    unlock_mutex(&queue->mutex);

    return result;
}
Пример #3
0
static OFDPE
delete_ether_device_from_switch( const uint32_t port_no ) {
  assert( port_no > 0 && port_no <= OFPP_MAX );

  if ( !lock_mutex( &mutex ) ) {
    return ERROR_LOCK;
  }

  switch_port *port = delete_switch_port( port_no );
  if ( port == NULL ) {
    return unlock_mutex( &mutex ) ? ERROR_INVALID_PARAMETER : ERROR_UNLOCK;
  }

  notify_port_status( port, OFPPR_DELETE );

  if ( port->device != NULL ) {
    delete_ether_device( port->device );
  }
  xfree( port );

  if ( !unlock_mutex( &mutex ) ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #4
0
status_t sys_delete_port( port_id hPort )
{
	Process_s *psProc = CURRENT_PROC;
	MsgPort_s *psPort;
	int nError;

	lock_mutex( g_hPortListSema, true );

	psPort = get_port_from_handle( hPort );
	if ( psPort == NULL )
	{
		printk( "Warning : Attempt to delete invalid message port %d\n", hPort );
		nError = -EINVAL;
		goto error;
	}

	if ( psPort->mp_hOwner != psProc->tc_hProcID )
	{
		printk( "Warning: Attempt to delete message port not owned by us(%d) but by %d\n", psProc->tc_hProcID, psPort->mp_hOwner );
		nError = -EACCES;
		goto error;
	}
	do_delete_port( psProc, psPort );
	unlock_mutex( g_hPortListSema );
	return ( 0 );
      error:
	unlock_mutex( g_hPortListSema );
	return ( nError );
}
Пример #5
0
CP_HIDDEN void cpi_wait_mutex(cpi_mutex_t *mutex) {
	DWORD self = GetCurrentThreadId();

	assert(mutex != NULL);
	lock_mutex(mutex->os_mutex);
	if (mutex->lock_count > 0
		&& self == mutex->os_thread) {
		int lc = mutex->lock_count;

		// Release mutex
		mutex->lock_count = 0;
		mutex->num_wait_threads++;
		set_event(mutex->os_cond_lock);
		unlock_mutex(mutex->os_mutex);

		// Wait for signal
		wait_for_event(mutex->os_cond_wake);

		// Reset wake signal if last one waking up
		lock_mutex(mutex->os_mutex);
		if (--mutex->num_wait_threads == 0) {
			reset_event(mutex->os_cond_wake);
		}

		// Re-acquire mutex and restore lock count for this thread
		lock_mutex_holding(mutex);
		mutex->lock_count = lc;

	} else {
		cpi_fatalf(_("Internal C-Pluff error: Unauthorized attempt at waiting on a mutex."));
	}
	unlock_mutex(mutex->os_mutex);
}
Пример #6
0
char* 
CoinMempool::alloc()
{
  lock_mutex();
  if (first_free_ == NULL) {
    unlock_mutex();
    char* block = allocate_new_block();
    lock_mutex();
#if (COIN_MEMPOOL_SAVE_BLOCKHEADS==1)
    // see if we can record another block head. If not, then resize
    // block_heads
    if (max_block_num_ == block_num_) {
      max_block_num_ = 2 * block_num_ + 10;
      char** old_block_heads = block_heads_;
      block_heads_ = (char**)malloc(max_block_num_ * sizeof(char*));
      CoinMemcpyN( old_block_heads,block_num_,block_heads_);
      free(old_block_heads);
    }
    // save the new block
    block_heads_[block_num_++] = block;
#endif
    // link in the new block
    *(char**)(block+((last_block_size_-1)*entry_size_)) = first_free_;
    first_free_ = block;
  }
  char* p = first_free_;
  first_free_ = *(char**)p;
  unlock_mutex();
  return p;
}
Пример #7
0
/*****************************************************************************
 * NAME:
 * DESC:
 * NOTE:
 * SEE ALSO:
 ****************************************************************************/
status_t make_port_private( port_id hPort )
{
	MsgPort_s *psPort;
	PublicPort_s *psPubPort;
	int nError = -EINVAL;

	psPort = get_port_from_handle( hPort );
	
	if ( psPort == NULL )
	{
		printk( "Error: make_port_private() called for invalid message port %d\n", hPort );
		nError = -EINVAL;
		goto error;
	}

	lock_mutex( g_hPubPortListSema, true );

	psPubPort = g_psPubPortListHead;

	
	while ( psPubPort != NULL )
	{

		if ( psPubPort->pp_hPortID == hPort )
		{
			if( psPubPort->pp_psPrev )
				psPubPort->pp_psPrev->pp_psNext = psPubPort->pp_psNext;
			if( psPubPort->pp_psNext )
				psPubPort->pp_psNext->pp_psPrev = psPubPort->pp_psPrev;
			else
				g_psPubPortListHead = psPubPort->pp_psPrev;

			kfree( psPubPort );

			lock_mutex( g_hPortListSema, true );

			psPort->mp_nFlags &= ~MSG_PORT_PUBLIC;

			unlock_mutex( g_hPortListSema );

			nError = EOK;
			break;
		}

		psPubPort = psPubPort->pp_psPrev;

	}
	

	unlock_mutex( g_hPubPortListSema );

	if ( nError == -EINVAL )
		printk( "Error: make_port_private() called with a non public port id %d\n", hPort );

      error:
	return ( nError );
}
Пример #8
0
/*****************************************************************************
 * NAME:
 * DESC:
 * NOTE:
 * SEE ALSO:
 ****************************************************************************/
status_t make_port_public( port_id hPort )
{
	MsgPort_s *psPort;
	PublicPort_s *psPubPort;
	int nError = EOK;
	
	psPort = get_port_from_handle( hPort );

	if ( psPort == NULL )
	{
		printk( "Error: make_port_public() called with invalid message port %d\n", hPort );
		nError = -EINVAL;
		goto error;
	}

	/* Ensure that the port name does not already exist in the public ports list */
	if ( do_find_port( psPort->mp_zName ) >= 0 )
	{
		printk( "make_port_public() : Attempt to make a duplicate port \"%s\" public\n", psPort->mp_zName );
		nError = -EEXIST;
		goto error;
	}

	psPubPort = kmalloc( sizeof( PublicPort_s ), MEMF_KERNEL | MEMF_LOCKED | MEMF_OKTOFAIL );

	if ( psPubPort == NULL )
	{
		printk( "Error: make_port_public() failed to alloc port struct\n" );
		nError = -ENOMEM;
		goto error;
	}

	psPubPort->pp_hPortID = psPort->mp_hPortID;
	psPubPort->pp_pzName = psPort->mp_zName;

	psPubPort->pp_psNext = NULL;
	psPubPort->pp_psPrev = g_psPubPortListHead;

	lock_mutex( g_hPubPortListSema, true );

	if ( NULL != g_psPubPortListHead )
		g_psPubPortListHead->pp_psNext = psPubPort;
	
	g_psPubPortListHead = psPubPort;

	unlock_mutex( g_hPubPortListSema );

	lock_mutex( g_hPortListSema, true );

	psPort->mp_nFlags |= MSG_PORT_PUBLIC;

	unlock_mutex( g_hPortListSema );

      error:
	return ( nError );
}
Пример #9
0
port_id sys_create_port( const char *const pzName, int nMaxCount )
{
	int nError;
	MsgPort_s *psPort;

	lock_mutex( g_hPortListSema, true );

	psPort = kmalloc( sizeof( MsgPort_s ), MEMF_CLEAR | MEMF_KERNEL | MEMF_LOCKED | MEMF_OKTOFAIL );

	if ( psPort == NULL )
	{
		nError = -ENOMEM;
		goto error1;
	}
	psPort->mp_hSyncSema = create_semaphore( "port_sync", 0, 0 );

	if ( psPort->mp_hSyncSema < 0 )
	{
		printk( "Error: sys_create_port() failed to allocate semaphore\n" );
		nError = psPort->mp_hSyncSema;
		goto error2;
	}
	psPort->mp_hPortID = MArray_Insert( &g_sMsgPorts, psPort, false );

	if ( psPort->mp_hPortID < 0 )
	{
		printk( "Failed to alloc descriptor for msg port %s\n", pzName );
		nError = psPort->mp_hPortID;
		goto error3;
	}
	psPort->mp_nMaxCount = nMaxCount;
	psPort->mp_nFlags = 0;
	strncpy_from_user( psPort->mp_zName, pzName, OS_NAME_LENGTH );
	psPort->mp_zName[OS_NAME_LENGTH - 1] = '\0';

	link_port( CURRENT_PROC, psPort );

	unlock_mutex( g_hPortListSema );

	atomic_inc( &g_sSysBase.ex_nMessagePortCount );

	return ( psPort->mp_hPortID );

      error3:
	delete_semaphore( psPort->mp_hSyncSema );
      error2:
	kfree( psPort );
      error1:
	unlock_mutex( g_hPortListSema );

	return ( nError );
}
Пример #10
0
OFDPE
get_port_description( const uint32_t port_no, port_description **descriptions, uint32_t *n_ports ) {
  assert( port_no > 0 || port_no == OFPP_ALL );
  assert( descriptions != NULL );
  assert( n_ports != NULL );

  if ( !lock_mutex( &mutex ) ) {
    return ERROR_LOCK;
  }

  *n_ports = 0;
  *descriptions = NULL;

  list_element *ports = NULL;
  if ( port_no != OFPP_ALL ) {
    switch_port *port = lookup_switch_port( port_no );
    if ( ports == NULL ) {
      return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK;
    }
    create_list( &ports );
    append_to_tail( &ports, port );
  }
  else {
    ports = get_all_switch_ports();
    if ( ports == NULL ) {
      return unlock_mutex( &mutex ) ? OFDPE_SUCCESS : ERROR_UNLOCK;
    }
  }

  *n_ports = ( uint32_t ) list_length_of( ports );
  size_t length = ( *n_ports ) * sizeof( port_description );
  *descriptions = xmalloc( length );
  memset( *descriptions, 0, length );

  port_description *description = *descriptions;
  for ( list_element *e = ports; e != NULL; e = e->next ) {
    assert( e->data != NULL );
    switch_port *port = e->data;
    assert( port->device != NULL );
    // FIXME: we assume that "port_description" is the same structure as "struct ofp_port".
    switch_port_to_ofp_port( description, port );
    description++;
  }

  if ( !unlock_mutex( &mutex ) ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #11
0
_Noreturn void exit_server(int retcode) {
	int err;
	interrupted = true;
	cleanup_ipc();

	lock_mutex(&counter_mutex);

	while(alive_threads > 0)
		if(0 != (err = pthread_cond_wait(&finish_cond, &counter_mutex)))
			serv_error("Unable to wait on finish_cond: %d", err);

	unlock_mutex(&counter_mutex);
	
	// mutexes, conditional variables and rwlocks are not destroyed,
	// because the main thread may possiby be blocked on it while handling
	// the signal and destroying mutexes/conds/rwlocks while they are used
	// results is undefined behaviour. Nevertheless, from now on we are sure
	// to have just one thread

	if(results)
		for(int i = 0; i < L; ++i)
			free((void *) results[i]);
	free((void*) results);
	free((void*) stations);
	exit(retcode ? EXIT_FAILURE : EXIT_SUCCESS);
}
Пример #12
0
static void local_error_msg (int loglevel,
			     const char *lib,
			     const char *fmt,
			     va_list ap)
{
#if _WIN32 && _DEBUG
  char msg[512];

  if (initialized) init_local_mutex();
  lock_mutex();
  sprintf(msg, "%s:", lib);
  OutputDebugString(msg);
  va_start(ap, fmt);
  _vsnprintf(msg, 512, fmt, ap);
  va_end(ap);
  OutputDebugString(msg);
  OutputDebugString("\n");
  unlock_mutex();
#else
  struct timeval thistime;
  char buffer[80];
  long int msec;

  gettimeofday(&thistime, NULL);
  strftime(buffer, sizeof(buffer), "%X", localtime(&thistime.tv_sec));
  msec = thistime.tv_usec / 1000;
  printf("%s.%03ld-%s-%d: ",
	 buffer,
	 msec,
	 lib,
	 loglevel);
  vprintf(fmt, ap);
  printf("\n");
#endif
}
Пример #13
0
void util_mutex_unlock(void)
{
        if(unlock_mutex)
                unlock_mutex(mutex_hnd);

        return;
}
Пример #14
0
void track::ins_row(unsigned short int which) {
    event *e,*deleted=NULL,*n=NULL;

    if (lock_mutex(song->hEditMutex, EDIT_LOCK_TIMEOUT)) {

        e = get_event(length-1);
        if (e) {
            n = (event *)e->next_event;
            deleted = e;
            delete e;
        }
        e = event_list;
        if (e == deleted) { 
            e = event_list = n;
        }
        while(e) {
            if (e->row>=which)
                e->row++;
            if (deleted) {
                if (e->next_event == deleted)
                    e->next_event = n;
            }
            e = (event *)e->next_event;
        }
        file_changed++;
        unlock_mutex(song->hEditMutex);
    }
}
Пример #15
0
OFDPE
finalize_port_manager() {
  bool ret = lock_mutex( &mutex );
  if ( !ret ) {
    return ERROR_LOCK;
  }

  delete_timer_event_safe( update_switch_port_status_and_stats, NULL );

  finalize_switch_port();

  config.max_send_queue_length = 0;
  config.max_recv_queue_length = 0;

  ret = unlock_mutex( &mutex );
  if ( !ret ) {
    return ERROR_UNLOCK;
  }

  ret = finalize_mutex( &mutex );
  if ( !ret ) {
    return ERROR_FINALIZE_MUTEX;
  }

  return OFDPE_SUCCESS;
}
Пример #16
0
OFDPE
init_port_manager( const size_t max_send_queue_length, const size_t max_recv_queue_length ) {
  if ( max_send_queue_length == 0 || max_recv_queue_length == 0 ) {
    error( "Failed to initialize port manager. Maximum queue length must be greater than zero "
           "( max_send_queue = %u, max_recv_queue = %u ).", max_send_queue_length, max_recv_queue_length );
    return ERROR_INVALID_PARAMETER;
  }

  bool ret = init_mutex( &mutex );
  if ( !ret ) {
    return ERROR_INIT_MUTEX;
  }

  ret = lock_mutex( &mutex );
  if ( !ret ) {
    return ERROR_LOCK;
  }

  config.max_send_queue_length = max_send_queue_length;
  config.max_recv_queue_length = max_recv_queue_length;

  init_switch_port();

  add_periodic_event_callback_safe( PORT_STATUS_UPDATE_INTERVAL, update_switch_port_status_and_stats, NULL );

  ret = unlock_mutex( &mutex );
  if ( !ret ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}
Пример #17
0
static VALUE
rb_sized_queue_max_set(VALUE self, VALUE value)
{
    Queue *queue;
    unsigned long new_capacity;
    unsigned long difference;
    Data_Get_Struct(self, Queue, queue);

    new_capacity = NUM2ULONG(value);

    if (new_capacity < 1) {
        rb_raise(rb_eArgError, "value must be positive");
    }

    lock_mutex(&queue->mutex);
    if (queue->capacity && new_capacity > queue->capacity) {
        difference = new_capacity - queue->capacity;
    } else {
        difference = 0;
    }
    queue->capacity = new_capacity;
    for (; difference > 0; --difference) {
        signal_condvar(&queue->space_available);
    }
    unlock_mutex(&queue->mutex);

    return self;
}
Пример #18
0
void Spider_Thread_Pool::push_work(void* sock)
{
	lock_mutex();
	m_work_queue.push(sock);
	post_semaphore();
	unlock_mutex();
}
Пример #19
0
/*****************************************************************************
 * NAME:
 * DESC:
 * NOTE:
 * SEE ALSO:
 ****************************************************************************/
port_id do_find_port( const char *pzPortname )
{
	PublicPort_s *psPubPort;
	port_id hPort = -1;

	if ( NULL == g_psPubPortListHead )
		goto error;

	lock_mutex( g_hPubPortListSema, true );

	psPubPort = g_psPubPortListHead;

	while ( psPubPort != NULL )
	{

		if ( !strcmp( psPubPort->pp_pzName, pzPortname ) )
		{
			hPort = psPubPort->pp_hPortID;
			break;
		}

		psPubPort = psPubPort->pp_psPrev;

	}

	unlock_mutex( g_hPubPortListSema );

      error:
	return ( hPort );
}
Пример #20
0
status_t sys_get_next_port_info( port_info * psInfo )
{
	port_info sInfo;
	MsgPort_s *psPort;
	port_id hPort;
	int nError;

	if ( memcpy_from_user( &hPort, &psInfo->pi_port_id, sizeof( hPort ) ) < 0 )
	{
		return ( -EFAULT );
	}

	lock_mutex( g_hPortListSema, true );
	hPort = MArray_GetNextIndex( &g_sMsgPorts, hPort );

	psPort = get_port_from_handle( hPort );
	if ( psPort == NULL )
	{
		nError = 0;
		goto error;
	}
	do_get_port_info( psPort, &sInfo );
	nError = 1;
	if ( memcpy_to_user( psInfo, &sInfo, sizeof( sInfo ) ) < 0 )
	{
		nError = -EFAULT;
	}
      error:
	unlock_mutex( g_hPortListSema );
	return ( nError );
}
Пример #21
0
status_t sys_get_port_info( port_id hPort, port_info * psInfo )
{
	port_info sInfo;
	MsgPort_s *psPort;
	int nError;

	lock_mutex( g_hPortListSema, true );
	if ( hPort == -1 )
	{
		hPort = MArray_GetNextIndex( &g_sMsgPorts, -1 );
	}
	psPort = get_port_from_handle( hPort );
	if ( psPort == NULL )
	{
		nError = -EINVAL;
		goto error;
	}
	do_get_port_info( psPort, &sInfo );
	nError = 0;
	if ( memcpy_to_user( psInfo, &sInfo, sizeof( sInfo ) ) < 0 )
	{
		nError = -EFAULT;
	}
      error:
	unlock_mutex( g_hPortListSema );
	return ( nError );
}
Пример #22
0
static void do_delete_port( Process_s *psProc, MsgPort_s *psPort )
{
	if ( psPort->mp_nFlags & MSG_PORT_PUBLIC )
	{
		unlock_mutex( g_hPortListSema );
		make_port_private( psPort->mp_hPortID );
		lock_mutex( g_hPortListSema, true );
	}

	MArray_Remove( &g_sMsgPorts, psPort->mp_hPortID );

	delete_semaphore( psPort->mp_hSyncSema );

	while ( psPort->mp_psFirstMsg != NULL )
	{
		MessageNode_s *psMsg = psPort->mp_psFirstMsg;

		psPort->mp_psFirstMsg = psMsg->mn_psNext;
		kfree( psMsg );
	}

	if ( psProc != NULL )
	{
		unlink_port( psProc, psPort );
	}

	kfree( psPort );
	atomic_dec( &g_sSysBase.ex_nMessagePortCount );

}
Пример #23
0
 inline void dealloc(char *p) 
 {
   char** pp = (char**)p;
   lock_mutex();
   *pp = first_free_;
   first_free_ = p;
   unlock_mutex();
 }
Пример #24
0
CP_HIDDEN int cpi_is_mutex_locked(cpi_mutex_t *mutex) {
	int locked;

	lock_mutex(mutex->os_mutex);
	locked = (mutex->lock_count != 0);
	unlock_mutex(mutex->os_mutex);
	return locked;
}
Пример #25
0
void exit_free_ports( Process_s *psProc )
{
	lock_mutex( g_hPortListSema, true );
	while ( psProc->pr_psFirstPort != NULL )
	{
		do_delete_port( psProc, psProc->pr_psFirstPort );
	}
	unlock_mutex( g_hPortListSema );
}
Пример #26
0
void enqueue_actor(struct Work_Queue *work_queue, struct Actor *actor) {
    actor->next = NULL;

    lock_mutex(work_queue->mutex_lock);
    {
        work_queue->tail->next = actor;
        work_queue->tail = actor;
    }
    unlock_mutex(work_queue->mutex_lock);
}
Пример #27
0
static void
update_switch_port_status_and_stats( void *user_data ) {
  if ( !lock_mutex( &mutex ) ) {
    return;
  }

  foreach_switch_port( update_switch_port_status_and_stats_walker, user_data );

  unlock_mutex( &mutex );
}
Пример #28
0
_Noreturn void exit_thread(void) {
	int err;

	lock_mutex(&counter_mutex);
	--alive_threads;

	if(0 == alive_threads) {
		unlock_mutex(&counter_mutex);
		if(0 != (err = pthread_cond_signal(&finish_cond)))
			serv_error("Unable to signal on finish_cond: %d", err);
	}
	else
		unlock_mutex(&counter_mutex);

	// Notify the server that it may spawn another thread
	if(0 != (err = pthread_cond_signal(&slot_cond)))
		serv_error("Unable to signal on slot_cond: %d", err);

	pthread_exit(NULL);
}
Пример #29
0
void	*malloc(size_t size)
{
  void	*res;

  if (lock_mutex() == FALSE)
    return (NULL);
  res = malloc_intern(size);
  if (unlock_mutex() == FALSE)
    return (NULL);
  return (res);
}
Пример #30
0
static OFDPE
add_ether_device_as_switch_port( const char *device, uint32_t port_no ) {
  assert( device != NULL );
  assert( port_no <= OFPP_MAX );

  if ( !lock_mutex( &mutex ) ) {
    return ERROR_LOCK;
  }

  if ( port_no == 0 ) {
    bool ret = get_free_switch_port_no( &port_no );
    if ( !ret ) {
      error( "No switch port number available ( device = %s ).", device );
      return unlock_mutex( &mutex ) ? ERROR_OFDPE_PORT_MOD_FAILED_BAD_PORT : ERROR_UNLOCK;
    }
  }

  bool ret = switch_port_exists( port_no );
  if ( ret ) {
    error( "Specified port already exists ( device = %s, port_no = %u ).", device, port_no );
    return unlock_mutex( &mutex ) ? ERROR_OFDPE_PORT_MOD_FAILED_BAD_PORT : ERROR_UNLOCK;
  }

  info( "Adding an Ethernet device as a switch port ( device = %s, port_no = %u ).", device, port_no );

  switch_port *port = add_switch_port( device, port_no, config.max_send_queue_length, config.max_recv_queue_length );
  if ( port == NULL ) {
    error( "Failed to add an Ethernet device as a switch port ( device = %s, port_no = %u ).", device, port_no );
    return unlock_mutex( &mutex ) ? ERROR_OFDPE_PORT_MOD_FAILED_EPERM : ERROR_UNLOCK;
  }

  set_frame_received_handler( port->device, handle_frame_received_on_switch_port, port );

  notify_port_status( port, OFPPR_ADD );

  if ( !unlock_mutex( &mutex ) ) {
    return ERROR_UNLOCK;
  }

  return OFDPE_SUCCESS;
}