?? antenna.c
字號:
/*************************************************************************** antenna.c - The antenna-implementation ------------------- begin : 2002 authors : Linus Gasser emails : linus.gasser@epfl.ch ***************************************************************************//*************************************************************************** Changes ------- date - name - description 02-10-01 - ineiti - create 02-12-11 - ineiti - Changed from a DMA-packed thing to a most general antenna. 03/08/18 - ineiti - changed dispatch-thread to FIFO-scheduling with priority 1 04/01/07 - ineiti - fixed race-condition while initialising the dispatcher and starting it. 04/03/29 - ineiti - deleted thread_join on exiting the dispatcher, because this doesn't seem to be possible 04/06/01 - ineiti - only one thread that works on all channels. This fixes problems with multi-threading and assures a more neat handling of MIMO situations **************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************//** * This is an interface to different channel-implementations. */#define DBG_LVL 0#define EXPORT_SYMTAB#include "system.h"#include "debugging.h"#include "memory.h"#include "antenna.h"#include "sdb.h"typedef struct { pthread_t thread; void *stack; pthread_cond_t cond; pthread_mutex_t mutex; int slot_len; int state; int offset; int ch_id[MAX_ANTENNAS]; swr_sdb_id notify_sdb[MAX_ANTENNAS];}dispatch_t;#define STATE_EXIT 0#define STATE_STOPPED 1#define STATE_RUNNING 2// The dispatcher threaddispatch_t disp_thread;// The array of the antenna-parametersswr_ant_param_t params[ MAX_ANTENNAS ];// How many antennas are initialised alreadyint initialised_antennas;/** * @short The dispatcher thread */void *ant_dispatch( void* arg ) { dispatch_t *this = &disp_thread; int nbr_ant, wait, blocks, slots; swr_ant_notify_t *notify; swr_usr_msg_t *msg; struct sched_param p; // Make this a FIFO-realtime thread. p.sched_priority = 1; pthread_setschedparam (pthread_self(), SCHED_FIFO, &p); // Initialising PR_DBG( 2, "Dispatcher started, initialising\n" ); wait = blocks = this->offset = slots = 0; // The main loop, once for each slot do { // Do the transmission, whatever it is, and wait for the next slot if ( wait > 0 ) { PR_DBG( 4, "Dispatcher is going to sleep for %i us\n", wait ); usleep( wait ); } else { PR_DBG( 4, "Not waiting\n" ); } if ( this->state == STATE_STOPPED ) { // Go to sleep PR_DBG( 4, "Dispatcher is waiting for further instructions\n" ); pthread_mutex_lock( &this->mutex ); pthread_cond_signal( &this->cond ); pthread_cond_wait( &this->cond, &this->mutex ); pthread_mutex_unlock( &this->mutex ); PR_DBG( 4, "Dispatcher is going to do %i\n", this->state ); } // Perhaps we have to quit if ( this->state == STATE_EXIT ) { PR_DBG( 4, "Going to exit\n" ); break; } // Notify all queues for ( nbr_ant=0; nbr_ant<initialised_antennas; nbr_ant++ ){ swr_sdb_id notify_sdb = this->notify_sdb[nbr_ant]; if ( notify_sdb >= 0 ) { PR_DBG( 4, "Notifying queue %i\n", nbr_ant ); msg = swr_malloc( sizeof( swr_usr_msg_t ) ); strcpy( msg->id, "ANT" ); notify = swr_malloc( sizeof( swr_ant_notify_t ) ); notify->blocks = blocks + this->offset; notify->slots = slots; notify->slot_begin = ( notify->blocks % params[ nbr_ant ].frame_blocks ) * DAQ_DMA_BLOCK_SIZE_BYTES; msg->data = notify; PR_DBG( 4, "Sending to id %i: slot %i, blocks %i, offset %i\n", notify_sdb, slots, blocks, this->offset ); swr_sdb_send_msg( this->notify_sdb[nbr_ant], SUBS_MSG_USER, msg, -1 ); PR_DBG( 4, "Sent message to %i\n", notify_sdb ); } } // The time up to the next slot blocks += this->slot_len; slots++; // Get the time in us to wait for the next slot to pass PR_DBG( 4, "How long do we have to wait?\n" ); wait = swr_ant_ch_io( blocks + this->offset ); PR_DBG( 4, "Finished while-loop and will wait for %i\n", wait ); } while ( this->state != STATE_EXIT ); PR_DBG( 3, "Byebye from the dispatcher\n" ); return NULL;}// The space we allocate for each thread#define THREAD_STACK_SIZE 16384/** * Initialises an antenna */int swr_ant_init( swr_sdb_id notify_sdb ) { pthread_attr_t attr; int id, ch; if ( ( id = swr_ant_ch_init( params + initialised_antennas ) ) < 0 ) { PR_DBG( 0, "Failed to initialise an antenna\n" ); return -1; } ch = initialised_antennas++; disp_thread.ch_id[ch] = id; disp_thread.notify_sdb[ch] = notify_sdb; if ( !ch ){ // We have to initialise the thread if ( disp_thread.state != STATE_EXIT ) { PR_DBG( 0, "Dispatcher %i already exists\n", initialised_antennas ); initialised_antennas--; return -1; } #ifndef REDHAT_TLS // Initialisation of the dispatcher-thread, needs it's own // stack. disp_thread.stack = swr_malloc( THREAD_STACK_SIZE ); if ( !disp_thread.stack ) goto start_dma_err_stack;#endif pthread_attr_init( &attr );#ifndef REDHAT_TLS pthread_attr_setstackaddr( &attr, disp_thread.stack ); pthread_attr_setstacksize( &attr, THREAD_STACK_SIZE );#endif pthread_attr_setfp_np( &attr, 1 ); disp_thread.state = STATE_STOPPED; disp_thread.offset = 0; pthread_cond_init( &disp_thread.cond, NULL ); pthread_mutex_init( &disp_thread.mutex, NULL ); pthread_mutex_lock( &disp_thread.mutex );#ifndef REDHAT_TLS if ( pthread_create( &disp_thread.thread, &attr, ant_dispatch, NULL ) < 0 )#else if ( pthread_create( &disp_thread.thread, NULL, ant_dispatch, NULL ) < 0 )#endif goto start_dma_err_pthread; pthread_attr_destroy( &attr ); // Wait for the thread to sleep with cond_wait pthread_cond_wait( &disp_thread.cond, &disp_thread.mutex ); pthread_mutex_unlock( &disp_thread.mutex ); } return id; start_dma_err_pthread: PR_DBG( 0, "Couldn't start ch_dispatch\n" ); pthread_attr_destroy( &attr );#ifndef REDHAT_TLS swr_free( disp_thread.stack ); start_dma_err_stack:#endif swr_ant_ch_free( ch ); PR_DBG( 0, "Error\n" ); return -1;}/** * @short Deletes an antenna */int swr_ant_free( int nbr_ant ) {// swr_ant_stop(); if ( nbr_ant >= MAX_ANTENNAS ) { PR_DBG( 0, "Asked for antenna %i, but only %i are available\n", nbr_ant, MAX_ANTENNAS ); return -1; } if ( disp_thread.state == STATE_EXIT ) { PR_DBG( 0, "Can't stop dispatcher: not initialised\n" ); return -1; } if ( !--initialised_antennas ){ // It's the last antenna, exit the dispatcher PR_DBG( 2, "Exit dispatcher\n" ); // First we have to stop the thread pthread_mutex_lock( &disp_thread.mutex ); disp_thread.state = STATE_EXIT; pthread_cond_signal( &disp_thread.cond ); pthread_mutex_unlock( &disp_thread.mutex ); PR_DBG( 2, "Dispatcher stopped\n" ); // Then wait for it to finish pthread_cancel( disp_thread.thread ); // pthread_join( disp_thread.thread, NULL ); PR_DBG( 2, "Thread cancelled (but not joined)\n" ); // And stop the channel swr_ant_ch_free( nbr_ant ); PR_DBG( 1, "Stopped Channel\n" ); // Free the mutex and conditional pthread_mutex_destroy( &disp_thread.mutex ); pthread_cond_destroy( &disp_thread.cond );#ifndef REDHAT_TLS // Then do some cleaning-up swr_free( disp_thread.stack );#endif } else { PR_DBG( 1, "Cleaned up one antenna\n" ); } return 0;}/** * @short Starts the antenna */int swr_ant_start( int blocks_per_frame ) { int nbr_ant; swr_ant_param_t *ant; PR_DBG( 1, "Starting antennas\n" ); // Put the dispatcher in running state
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -