void taskh_func(long tid) { RTIME time; unsigned int msg = 0, wait; rt_send(&taskm, msg); rt_send(&taskl, msg); while (1) { rt_receive(&taskm, &msg); time = rt_get_time_ns(); if (MUTEX_LOCK(&mutex) <= 1) { if ((wait = (int)(rt_get_time_ns() - time)) > 250000) { rt_printk("PRIORITY INVERSION, WAITED FOR %d us\n", wait/1000); } else { rt_printk("NO PRIORITY INVERSION, WAITED FOR %d us\n", wait/1000); } if (SemType) { MUTEX_LOCK(&mutex); MUTEX_LOCK(&mutex); rt_busy_sleep(100000); MUTEX_LOCK(&mutex); } rt_busy_sleep(100000); if (SemType) { rt_sem_signal(&mutex); rt_busy_sleep(100000); rt_sem_signal(&mutex); rt_sem_signal(&mutex); } rt_sem_signal(&mutex); } else { rt_task_suspend(0); } } }
int signal_func(void *param) { RT_TASK *rt_signal; //TODO: RTIME sampling; int value = 0; int rval = 0; char name[8]; t_info *t = param; snprintf(name, 8, "S_%c", t->id); printf("%s\n", name); rt_signal = rt_thread_init(nam2num(name), 0, 0, SCHED_FIFO, CPUMAP); if (!rt_signal) { printf("Could not init real time signal %c\n", t->id); rval = -ENODEV; goto exit; } rt_task_make_periodic(rt_signal, rt_get_time() + t->period + t->delay, t->period); while (!finish) { value = !value; printf("[%Ld] signal %c now in %s.\n", rt_get_time_ns(), t->id, value ? "up" : "down"); rt_task_wait_period(); } rt_task_delete(rt_signal); exit: pthread_exit(NULL); return rval; }
void process(void* arg) { while(1) { rt_sem_wait(&tx_sem); tx_time = rt_get_time_ns(); /* send the time */ if (sendto_rt(sock, &tx_time, sizeof(RTIME), 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)) < 0) break; } }
void *process(void * arg) { int ret = 0; while(1) { rt_sem_wait(&tx_sem); /* get time */ tx_time = rt_get_time_ns(); /* send the time */ ret=rt_socket_sendto(sock, &tx_time, sizeof(RTIME), 0, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)); } }
void *process(void * arg) { int ret = 0; while(1) { /* get time */ tx_time = rt_get_time_ns(); /* send the time */ ret=rt_socket_sendto(sock, &tx_time, sizeof(RTIME), 0, (struct sockaddr *) &broadcast_addr, sizeof(struct sockaddr_in)); /* wait one period */ rt_task_wait_period(); } }
int echo_rcv(int s,void *arg) { int ret=0; struct msghdr msg; struct iovec iov; struct sockaddr_in addr; memset(&msg,0,sizeof(msg)); iov.iov_base=&buffer; iov.iov_len=BUFSIZE; msg.msg_name=&addr; msg.msg_namelen=sizeof(addr); msg.msg_iov=&iov; msg.msg_iovlen=1; msg.msg_control=NULL; msg.msg_controllen=0; ret=rt_socket_recvmsg(sock, &msg, 0); if ( (ret>0) && (msg.msg_namelen==sizeof(struct sockaddr_in)) ) { union { unsigned long l; unsigned char c[4]; } rcv; struct sockaddr_in *sin = msg.msg_name; outb(0x08, PAR_DATA); outb(0x18, PAR_DATA); /* get the time */ rx_time = rt_get_time_ns(); memcpy (&tx_time, buffer, sizeof(RTIME)); rtf_put(PRINT, &rx_time, sizeof(RTIME)); rtf_put(PRINT, &tx_time, sizeof(RTIME)); /* copy the address */ rcv.l = sin->sin_addr.s_addr; //rt_sem_signal(&tx_sem); } return 0; }
int echo_rcv(int s,void *arg) { int ret=0; struct msghdr msg; struct iovec iov; struct sockaddr_in addr; struct mrtt_rx_packet rx_packet; if (closing) rt_printk("In echo_rcv\n"); memset(&msg, 0, sizeof(msg)); iov.iov_base = &buffer; iov.iov_len = BUFSIZE; msg.msg_name = &addr; msg.msg_namelen = sizeof(addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_control = NULL; msg.msg_controllen = 0; ret = rt_socket_recvmsg(sock, &msg, 0); if ( (ret>0) && (msg.msg_namelen==sizeof(struct sockaddr_in)) ) { struct sockaddr_in *sin = msg.msg_name; /* get the time */ rx_time = rt_get_time_ns(); memcpy(&tx_time, buffer, sizeof(RTIME)); rx_packet.rx = rx_time; rx_packet.tx = tx_time; rx_packet.ip_addr = sin->sin_addr.s_addr; rtf_put(PRINT, &rx_packet, sizeof(struct mrtt_rx_packet)); } if (closing) rt_printk("Exit echo_rcv\n"); return 0; }
void init_uniform (void) { #ifdef USER_MODE struct timeval tv; struct timezone tz; gettimeofday (&tv, &tz); seed = (int) tv.tv_usec; #ifdef NODE_MT #warning TO DO seed = mobileId //seed += mobileId; #endif #ifdef NODE_RG #warning TO DO seed = rgId //seed += rgId; #endif #else seed = rt_get_time_ns(); #endif }
void echo_rcv(void *arg) { int ret; struct msghdr msg; struct iovec iov; struct sockaddr_in addr; while (1) { iov.iov_base=&buffer; iov.iov_len=BUFSIZE; msg.msg_name=&addr; msg.msg_namelen=sizeof(addr); msg.msg_iov=&iov; msg.msg_iovlen=1; msg.msg_control=NULL; msg.msg_controllen=0; ret = recvmsg_rt(sock, &msg, 0); if ((ret > 0) && (msg.msg_namelen == sizeof(struct sockaddr_in))) { union { unsigned long l; unsigned char c[4]; } rcv; struct sockaddr_in *sin = msg.msg_name; outb(0xEF, PAR_DATA); outb(0xFF, PAR_DATA); /* get the time */ rx_time = rt_get_time_ns(); memcpy (&tx_time, buffer, sizeof(RTIME)); rtf_put(PRINT_FIFO, &rx_time, sizeof(RTIME)); rtf_put(PRINT_FIFO, &tx_time, sizeof(RTIME)); /* copy the address */ rcv.l = sin->sin_addr.s_addr; } } }
/* Write an individual PDU (PCAP packet header + mac-context + mac-pdu) */ static int MAC_LTE_PCAP_WritePDU(MAC_Context_Info_t *context, const uint8_t *PDU, unsigned int length) { pcaprec_hdr_t packet_header; uint8_t context_header[256]; int offset = 0; unsigned short tmp16; /*****************************************************************/ /* Context information (same as written by UDP heuristic clients */ context_header[offset++] = context->radioType; context_header[offset++] = context->direction; context_header[offset++] = context->rntiType; /* RNTI */ context_header[offset++] = MAC_LTE_RNTI_TAG; tmp16 = htons(context->rnti); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* UEId */ context_header[offset++] = MAC_LTE_UEID_TAG; tmp16 = htons(context->ueid); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* Subframe number */ context_header[offset++] = MAC_LTE_SUBFRAME_TAG; tmp16 = htons(context->subFrameNumber); memcpy(context_header+offset, &tmp16, 2); offset += 2; /* CRC Status */ context_header[offset++] = MAC_LTE_CRC_STATUS_TAG; context_header[offset++] = context->crcStatusOK; /* Data tag immediately preceding PDU */ context_header[offset++] = MAC_LTE_PAYLOAD_TAG; /****************************************************************/ /* PCAP Header */ /* TODO: Timestamp might want to be relative to a more sensible base time... */ #if defined(RTAI) { unsigned long long int current_ns; current_ns = rt_get_time_ns(); packet_header.ts_sec = current_ns / 1000000000UL; packet_header.ts_usec = current_ns % 1000; } #else packet_header.ts_sec = context->subframesSinceCaptureStart / 1000; packet_header.ts_usec = (context->subframesSinceCaptureStart % 1000) * 1000; #endif packet_header.incl_len = offset + length; packet_header.orig_len = offset + length; /***************************************************************/ /* Now write everything to the file */ fwrite(&packet_header, sizeof(pcaprec_hdr_t), 1, file_fd); fwrite(context_header, 1, offset, file_fd); fwrite(PDU, 1, length, file_fd); return 1; }
int PLLReferenceGeneration() { //Initial test function to try out Real time stuff. int m, i=0, err, n; lsampl_t data_to_card; static comedi_t * dev; static int OutputFIFOBufferSize; static int PLLGenerationBufferSize; unsigned int maxdata; unsigned int chanlist[16]; int ret; static lsampl_t data[PLLGenerationBufferNPoints]; //this is the buffer used to send data points out comedi_cmd cmd; dev = comedi_open(device_names[PLLReferenceGenerationChannel.board_number]); //Check the size of the output buffer OutputFIFOBufferSize = comedi_get_buffer_size(dev, PLLReferenceGenerationChannel.subdevice); rt_printk("OutputFIFO Buffer size is %i\n", OutputFIFOBufferSize); //Set the actual buffer size that we will be using to half this and the number of data points to one fourth //Now configure the output channel using a Comedi instruction //BufferSize is initially set to be double the number of PLLGenerationBufferNPoints PLLGenerationBufferSize = 2*PLLGenerationBufferNPoints; maxdata = comedi_get_maxdata(dev, PLLReferenceGenerationChannel.subdevice, PLLReferenceGenerationChannel.channel); rt_printk("PLL Reference channel max data is %i\n", maxdata); offset = maxdata / 2; amplitude = maxdata - offset; memset(&cmd,0,sizeof(cmd)); cmd.subdev = PLLReferenceGenerationChannel.subdevice; cmd.flags = CMDF_WRITE; cmd.start_src = TRIG_INT; cmd.start_arg = 0; cmd.scan_begin_src = TRIG_TIMER; cmd.scan_begin_arg = PLLGenMinPulseTime; //minimum update time for the cmd.convert_src = TRIG_NOW; cmd.convert_arg = 0; cmd.scan_end_src = TRIG_COUNT; cmd.scan_end_arg = NCHAN; //only one channel cmd.stop_src = TRIG_NONE; cmd.stop_arg = 0; cmd.chanlist = chanlist; cmd.chanlist_len = NCHAN; chanlist[0] = CR_PACK(PLLReferenceGenerationChannel.channel, AO_RANGE, AREF_GROUND); dds_init(PLLWaveformFrequency, PLLUpdateFrequency); err = comedi_command_test(dev, &cmd); if (err < 0) { comedi_perror("comedi_command_test"); exit(1); } err = comedi_command_test(dev, &cmd); if (err < 0) { comedi_perror("comedi_command_test"); exit(1); } if ((err = comedi_command(dev, &cmd)) < 0) { comedi_perror("comedi_command"); exit(1); } dds_output(data,PLLGenerationBufferNPoints); n = PLLGenerationBufferNPoints * sizeof(sampl_t); m = write(comedi_fileno(dev), (void *)data, n); if(m < 0){ perror("write"); exit(1); }else if(m < n) { fprintf(stderr, "failed to preload output buffer with %i bytes, is it too small?\n" "See the --write-buffer option of comedi_config\n", n); exit(1); } if(!(PLLRefGen_Task = rt_task_init_schmod(nam2num( "PLLReferenceGeneration" ), // Name 2, // Priority 0, // Stack Size 0, //, // max_msg_size SCHED_FIFO, // Policy CPUMAP ))) // cpus_allowed { printf("ERROR: Cannot initialize pll reference generation task\n"); exit(1); } //specify that this is to run on one CPU rt_set_runnable_on_cpuid(PLLRefGen_Task, 1); //Convert samp_time, which is in nanoseconds, to tick time //sampling_interval = nano2count(SAMP_TIME); //Converts a value from //nanoseconds to internal count units. mlockall(MCL_CURRENT|MCL_FUTURE); rt_make_hard_real_time(); PLLUpdateTime = nano2count(PLLGenerationLoopTime); rt_printk("PLL generation update time is %f12 \n",count2nano((float) PLLUpdateTime)); // Let's make this task periodic.. expected = rt_get_time() + 100*PLLUpdateTime; rt_task_make_periodic(PLLRefGen_Task, expected, PLLUpdateTime); //period in counts //rt_task_resume(Sinewaveloop_Task); PLLGenerationOn = TRUE; // Concurrent function Loop //rt_printk("SineWaveAmplitude is is %f \n",SineWaveAmplitude); //rt_printk("SineWaveFrequency is %f \n",SineWaveFrequency); //rt_printk("sine_loop_running is %d \n",sine_loop_running); //rt_printk("SAMP_TIME is %d \n",SAMP_TIME); start_time = (float)rt_get_time_ns()/1E9; //in seconds old_time = start_time; rt_printk("PLLReferenceGenerationChannel board_it is %p \n",PLLReferenceGenerationChannel.board_id); rt_printk("PLLReferenceGenerationChannel devicename is %p \n",*(PLLReferenceGenerationChannel.devicename)); rt_printk("PLLReferenceGenerationChannel boardname is %p \n",*(PLLReferenceGenerationChannel.boardname)); rt_printk("PLLReferenceGenerationChannel subdevice is %d \n",PLLReferenceGenerationChannel.subdevice); rt_printk("PLLReferenceGenerationChannel channel is %d \n",PLLReferenceGenerationChannel.channel); OutputValue = 1; PLLGenerationBufferSize = comedi_get_buffer_size(dev, PLLReferenceGenerationChannel.subdevice); //sine_loop_running = 0; //set this to 0 for testing while(PLLGenerationOn) { i++; // Count Loops. current_time = (float)rt_get_time_ns()/1E9; //rt_printk("LOOP %d,-- Period time: %f12 %f12\n",i, current_time - old_time,count2nano((float)sampling_interval)/1E9); OutputValue = SineWaveAmplitude*sin(2*PI*SineWaveFrequency*(current_time-start_time)); //OutputValue = -1*OutputValue; //rt_printk("OutputValue is %f12 \n",OutputValue); data_to_card = (lsampl_t) nearbyint(((OutputValue - MinOutputVoltage)/OutputRange)*MaxOutputBits); //m=rt_comedi_command_data_write(AnalogOutputChannel.board_id, AnalogOutputChannel.subdevice, NCHAN, data_to_card); comedi_lock(dev, AnalogOutputChannel.subdevice); m=comedi_data_write(dev, AnalogOutputChannel.subdevice, AnalogOutputChannel.channel, AO_RANGE, AREF_DIFF, data_to_card); comedi_unlock(dev, AnalogOutputChannel.subdevice); // m=comedi_data_write(AnalogOutputChannel.board_id, AnalogOutputChannel.subdevice, // AnalogOutputChannel.channel, AO_RANGE, AREF_GROUND, data_to_card); //rt_printk("Data_to_card is %d; result from rt_comedi_command_data_write is %d \n",data_to_card, m); //rt_printk("LOOP %d,-- AO Out time: %f12 \n",i, (float)rt_get_time_ns()/1E9 - current_time); //rt_printk("Data_to_card is %d \n",data_to_card); //old_time = current_time; /* if (i== 100000) { sine_loop_running = 0; //printf("LOOP -- run: %d %d\n ",keep_on_running,&keep_on_running); //printf("RTAI LOOP -- run: %d \n ",i); break; } */ rt_task_wait_period(); // And waits until the end of the period. } rt_make_soft_real_time(); comedi_close(dev); rt_task_delete(Sinewaveloop_Task); //Self termination at end. pthread_exit(NULL); return 0; }
NANO_TIME rtos_get_time_ns(void) { return rt_get_time_ns(); }
int main(int argc, char *argv[]) { RT_TASK *task; RTIME trp, max = 0, min = 1000000000, avrg = 0; int sockfd, ret, hard_timer_running, i; struct sockaddr_in local_addr, server_addr; struct { long long count; char msg[100]; } msg = { 0LL, "this message was sent using rtnet-rtai." }; signal(SIGTERM, sigh); signal(SIGINT, sigh); signal(SIGHUP, sigh); /* Set address structures to zero. */ memset(&local_addr, 0, sizeof(struct sockaddr_in)); memset(&server_addr, 0, sizeof(struct sockaddr_in)); /* Check arguments and set addresses. */ if (argc == 6) { local_addr.sin_family = AF_INET; local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_port = htons(atoi(argv[1])); server_addr.sin_family = AF_INET; inet_aton(argv[2], &server_addr.sin_addr); server_addr.sin_port = htons(atoi(argv[3])); NR_TRIPS = atoi(argv[4]); PERIOD = atoi(argv[5])*1000LL; } else { fprintf(stderr, "Usage: " "%s <local-port> " "<server-ip> <server-port> " "<number-of-trips> <sending-period-us>\n", argv[0]); return 1; } /* Create new socket. */ sockfd = rt_dev_socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { printf("Error opening socket: %d\n", sockfd); return 1; } /* Link the Linux process to RTAI. */ if (!(hard_timer_running = rt_is_hard_timer_running())) { start_rt_timer(0); } task = rt_thread_init(nam2num("SMPCLT"), 1, 0, SCHED_OTHER, 0xFF); if (task == NULL) { rt_dev_close(sockfd); printf("CANNOT LINK LINUX SIMPLECLIENT PROCESS TO RTAI\n"); return 1; } /* Lock allocated memory into RAM. */ printf("RTnet, simpleclient for RTAI (user space).\n"); mlockall(MCL_CURRENT|MCL_FUTURE); /* Switch over to hard realtime mode. */ rt_make_hard_real_time(); /* Bind socket to local address specified as parameter. */ ret = rt_dev_bind(sockfd, (struct sockaddr *)&local_addr, sizeof(struct sockaddr_in)); /* Specify destination address for socket; needed for rt_socket_send(). */ rt_dev_connect(sockfd, (struct sockaddr *) &server_addr, sizeof(struct sockaddr_in)); /* Send messages */ for (i = 1; i <= NR_TRIPS && !end; i++) { rt_sleep(nano2count(PERIOD)); msg.count = i; trp = rt_get_time_ns(); rt_dev_send(sockfd, &msg, sizeof(long long) + strlen(msg.msg) + 1, 0); rt_dev_recv(sockfd, &msg, sizeof(msg), 0); trp = (msg.count - trp)/1000; if (trp < min) min = trp; if (i > 3 && trp > max) max = trp; avrg += trp; printf("Client received: trip time %lld (us), %s\n", trp, msg.msg); } msg.count = -1; rt_dev_send(sockfd, &msg, sizeof(long long) + strlen(msg.msg) + 1, 0); /* Switch over to soft realtime mode. */ rt_make_soft_real_time(); /* Close socket, must be in soft-mode because socket was created as non-rt. */ rt_dev_close(sockfd); /* Unlink the Linux process from RTAI. */ if (!hard_timer_running) { stop_rt_timer(); } rt_task_delete(task); printf("Min trip time %lld, Max trip time %lld, Average trip time %lld\n", min, max, avrg/i); return 0; }
/** RX_PDSCH Decoding Thread */ static void * rx_pdsch_thread(void *param) { //unsigned long cpuid; uint8_t rx_pdsch_thread_index = 0; uint8_t dlsch_thread_index = 0; uint8_t pilot1,pilot2,pilot3,harq_pid,subframe; // uint8_t last_slot; uint8_t dual_stream_UE = 0; uint8_t i_mod = 0; RTIME time_in,time_out; #ifdef RTAI RT_TASK *task; #endif int m,eNB_id = 0; int eNB_id_i = 1; PHY_VARS_UE *UE = PHY_vars_UE_g[0]; #ifdef RTAI task = rt_task_init_schmod(nam2num("RX_PDSCH_THREAD"), 0, 0, 0, SCHED_FIFO, 0xF); if (task==NULL) { LOG_E(PHY,"[SCHED][RX_PDSCH] Problem starting rx_pdsch thread!!!!\n"); return 0; } else { LOG_I(PHY,"[SCHED][RX_PDSCH] rx_pdsch_thread started for with id %p\n",task); } #endif mlockall(MCL_CURRENT | MCL_FUTURE); //rt_set_runnable_on_cpuid(task,1); //cpuid = rtai_cpuid(); #ifdef HARD_RT rt_make_hard_real_time(); #endif if (UE->lte_frame_parms.Ncp == 0) { // normal prefix pilot1 = 4; pilot2 = 7; pilot3 = 11; } else { // extended prefix pilot1 = 3; pilot2 = 6; pilot3 = 9; } while (!oai_exit){ vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 0); if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) { LOG_E(PHY,"[SCHED][RX_PDSCH] error locking mutex.\n"); } else { while (rx_pdsch_instance_cnt < 0) { pthread_cond_wait(&rx_pdsch_cond,&rx_pdsch_mutex); } if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) { LOG_E(PHY,"[SCHED][RX_PDSCH] error unlocking mutex.\n"); } } vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_THREAD, 1); // last_slot = rx_pdsch_slot; subframe = UE->slot_rx>>1; // Important! assumption that PDCCH procedure of next SF is not called yet harq_pid = UE->dlsch_ue[eNB_id][0]->current_harq_pid; UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->G = get_G(&UE->lte_frame_parms, UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->nb_rb, UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rb_alloc, get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs), UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->Nl, UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, UE->frame_rx,subframe); if ((UE->transmission_mode[eNB_id] == 5) && (UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->dl_power_off==0) && (openair_daq_vars.use_ia_receiver > 0)) { dual_stream_UE = 1; eNB_id_i = UE->n_connected_eNB; if (openair_daq_vars.use_ia_receiver == 2) { i_mod = get_Qm(((UE->frame_rx%1024)/3)%28); } else { i_mod = get_Qm(UE->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); } } else { dual_stream_UE = 0; eNB_id_i = eNB_id+1; i_mod = 0; } if (oai_exit) break; LOG_D(PHY,"[SCHED][RX_PDSCH] Frame %d, slot %d: Calling rx_pdsch_decoding with harq_pid %d\n",UE->frame_rx,UE->slot_rx,harq_pid); time_in = rt_get_time_ns(); // Check if we are in even or odd slot if (UE->slot_rx%2) { // odd slots // measure time //time0 = rt_get_time_ns(); // rt_printk("[SCHED][RX_PDSCH][before rx_pdsch] Frame %d, slot %d, time %llu\n",UE->frame,last_slot,rt_get_time_ns()); for (m=pilot2;m<UE->lte_frame_parms.symbols_per_tti;m++) { rx_pdsch(UE, PDSCH, eNB_id, eNB_id_i, subframe, m, 0, dual_stream_UE, i_mod, harq_pid); } // time1 = rt_get_time_ns(); // rt_printk("[SCHED][RX_PDSCH] Frame %d, slot %d, start %llu, end %llu, proc time: %llu ns\n",UE->frame_rx,last_slot,time0,time1,(time1-time0)); dlsch_thread_index = harq_pid; if (pthread_mutex_lock (&dlsch_mutex[dlsch_thread_index]) != 0) { // Signal MAC_PHY Scheduler LOG_E(PHY,"[UE %d] ERROR pthread_mutex_lock\n",UE->Mod_id); // lock before accessing shared resource // vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); //return(-1); } dlsch_instance_cnt[dlsch_thread_index]++; dlsch_subframe[dlsch_thread_index] = subframe; pthread_mutex_unlock (&dlsch_mutex[dlsch_thread_index]); if (dlsch_instance_cnt[dlsch_thread_index] == 0) { if (pthread_cond_signal(&dlsch_cond[dlsch_thread_index]) != 0) { LOG_E(PHY,"[UE %d] ERROR pthread_cond_signal for dlsch_cond[%d]\n",UE->Mod_id,dlsch_thread_index); // vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); //return(-1); } } else { LOG_W(PHY,"[UE %d] DLSCH thread for dlsch_thread_index %d busy!!!\n",UE->Mod_id,dlsch_thread_index); // vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT); //return(-1); } } else { // even slots for (m=UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols;m<pilot2;m++) { rx_pdsch(UE, PDSCH, eNB_id, eNB_id_i, subframe, m, (m==UE->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols)?1:0, // first_symbol_flag dual_stream_UE, i_mod, harq_pid); } } time_out = rt_get_time_ns(); if (pthread_mutex_lock(&rx_pdsch_mutex) != 0) { msg("[openair][SCHED][RX_PDSCH] error locking mutex.\n"); } else { rx_pdsch_instance_cnt--; if (pthread_mutex_unlock(&rx_pdsch_mutex) != 0) { msg("[openair][SCHED][RX_PDSCH] error unlocking mutex.\n"); } } } #ifdef HARD_RT rt_make_soft_real_time(); #endif LOG_D(PHY,"[openair][SCHED][RX_PDSCH] RX_PDSCH thread exiting\n"); return 0; }
void* TrackerSim::_thread(void *arg) { RT_TASK *rt_task; RTIME interval = nano2count(_read_interval_ms * 1E6); MBX *mbx_tracker; int val; rt_allow_nonroot_hrt(); mlockall(MCL_CURRENT | MCL_FUTURE); // create task rt_task = rt_task_init_schmod(nam2num("TSKTRA"), 2, 0, 0, SCHED_FIFO, rttools::cpu_id(0)); if (!rt_task) { ERROR("Cannot init TRACKER task"); pthread_exit(NULL); } mbx_tracker = rttools::get_mbx(MBX_TRACKER_NAME, MBX_TRACKER_BLOCK * sizeof(trackerdata_t)); if (!mbx_tracker) { ERROR("Cannot init TRACKER mailbox"); rt_task_delete(rt_task); pthread_exit(NULL); } while (_running) { // simulate the current position switch (_sim_type) { case constant: sim_constant(); break; case calculated: sim_calculated_az(); //sim_calculated_el(); break; case from_file: sim_from_file(); break; case cipic_angles: sim_cipic_angles(); break; } _data.timestamp = (unsigned long) rt_get_time_ns(); // send message (non-blocking) val = rt_mbx_send_if(mbx_tracker, &_data, sizeof(trackerdata_t)); if (-EINVAL == val) { ERROR("Mailbox is invalid"); break; } rt_sleep(interval); } rt_task_delete(rt_task); rttools::del_mbx(MBX_TRACKER_NAME); return arg; }
/* This is the main eNB thread. It gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */ static void *eNB_thread(void *arg) { #ifdef RTAI RT_TASK *task; RTIME now; #endif unsigned char slot=0,last_slot, next_slot; int hw_slot,frame=0; unsigned int msg1; unsigned int aa,slot_offset, slot_offset_F; int diff; int delay_cnt; RTIME time_in, time_diff; int mbox_target=0,mbox_current=0; int i,ret; int tx_offset; int bytes; #ifdef RTAI task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); LOG_D(HW,"Started eNB thread (id %p)\n",task); #ifndef TIMER_ONESHOT_MODE now = rt_get_time(); ret = rt_task_make_periodic(task, now, nano2count(500000LL)); if (ret!=0) LOG_E(HW,"Problem with periodic timer\n"); #endif #endif #ifdef HARD_RT rt_make_hard_real_time(); #endif mlockall(MCL_CURRENT | MCL_FUTURE); timing_info.time_min = 100000000ULL; timing_info.time_max = 0; timing_info.time_avg = 0; timing_info.n_samples = 0; while (!oai_exit) { hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //LOG_D(HW,"eNB frame %d, time %llu: slot %d, hw_slot %d (mbox %d)\n",frame,rt_get_time_ns(),slot,hw_slot,((unsigned int *)DAQ_MBOX)[0]); //this is the mbox counter where we should be //mbox_target = ((((slot+1)%20)*15+1)>>1)%150; mbox_target = mbox_bounds[slot]; //this is the mbox counter where we are mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD) if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround diff = 150-mbox_current+mbox_target; else if ((mbox_current<15) && (mbox_target>=135)) diff = -150+mbox_target-mbox_current; else diff = mbox_target - mbox_current; vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_ENB, slot); vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_ENB, frame); vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *((volatile unsigned int *) openair0_exmimo_pci[card].rxcnt_ptr[0])); vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff); time_in = rt_get_time_ns(); //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in); //LOG_D(HW,"eNB Frame %d, time %llu: sleeping for %llu (slot %d, hw_slot %d, diff %d, mbox %d, delay_cnt %d)\n", frame, time_in, diff*DAQ_PERIOD,slot,hw_slot,diff,((volatile unsigned int *)DAQ_MBOX)[0],delay_cnt); vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1); #ifdef TIMER_ONESHOT_MODE //ret = rt_sleep_ns(DAQ_PERIOD * (slot%4==0?6:8)); ret = rt_sleep_ns(500000); if (ret) LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in); #else rt_task_wait_period(); #endif vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0); //hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0]; if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround diff = 150-mbox_current+mbox_target; else if ((mbox_current<15) && (mbox_target>=135)) diff = -150+mbox_target-mbox_current; else diff = mbox_target - mbox_current; last_slot = (slot)%LTE_SLOTS_PER_FRAME; if (last_slot <0) last_slot+=20; next_slot = (slot+3)%LTE_SLOTS_PER_FRAME; slot++; if (slot==20) { slot=0; frame++; } if (frame==1000) oai_exit=1; #if defined(ENABLE_ITTI) itti_update_lte_time(frame, slot); #endif } LOG_D(HW,"eNB_thread: finished, ran %d times.\n",frame); #ifdef HARD_RT rt_make_soft_real_time(); #endif // clean task #ifdef RTAI rt_task_delete(task); #endif LOG_D(HW,"Task deleted. returning\n"); return 0; }
static void* rt_system_thread(void * arg) { struct timeval tv; int64_t ts1, ts2; SEM * shm_sem; SEM * sync_sem; RT_TASK *task; M3EcSystemShm * sys = (M3EcSystemShm *)arg; printf("Starting real-time thread\n",0); RTIME t_last; int cntr=0; task = rt_task_init_schmod(nam2num("M3SYSP"), 0, 0, 0, SCHED_FIFO, 0xF); rt_allow_nonroot_hrt(); if (task==NULL) { printf("Failed to create RT-TASK M3SYSP\n",0); return 0; } shm_sem=(SEM*)rt_get_adr(nam2num(SEMNAM_M3LSHM)); if (!shm_sem) { printf("Unable to find the SEMNAM_M3LSHM semaphore.\n",0); rt_task_delete(task); return 0; } //else // printf("Allocated shm_sem semaphore %08x \n",shm_sem); sync_sem=(SEM*)rt_get_adr(nam2num(SEMNAM_M3SYNC)); if (!sync_sem) { printf("Unable to find the SEMNAM_M3SYNC semaphore.\n",0); rt_task_delete(task); rt_sem_delete(shm_sem); return 0; } //else // printf("Allocated sync_sem semaphore %08x \n",sync_sem); RTIME tick_period = nano2count(RT_TIMER_TICKS_NS); RTIME now = rt_get_time(); rt_task_make_periodic(task, now + tick_period, tick_period); mlockall(MCL_CURRENT | MCL_FUTURE); rt_make_hard_real_time(); t_last=now; sys_thread_active=1; uint64_t tl; while(!sys_thread_end) { rt_sem_wait(sync_sem); rt_sem_wait(shm_sem); if (cntr%200==0) { now=rt_get_time_ns(); float dt = (now-t_last)/1000000.0; count2timeval(nano2count(rt_get_real_time_ns()), &tv); printf("\n\nM3 Cycle: %d: 200 cycles in %4.3f ms. EC cycles: %d\n", cntr,dt, sys->counter); printf("DT: timestamp_dt (uS) : %lld\n",(sys->timestamp_ns-tl)/1000); t_last=now; SysEcShmPrettyPrint(sys); } tl=sys->timestamp_ns; cntr++; rt_sem_signal(shm_sem); rt_task_wait_period(); } printf("Exiting RealTime Thread...\n",0); rt_make_soft_real_time(); rt_task_delete(task); sys_thread_active=0; return 0; }
/** ULSCH Decoding Thread */ static void * ulsch_thread(void *param) { //unsigned long cpuid; unsigned int ulsch_thread_index = (unsigned int)param; RTIME time_in,time_out; #ifdef RTAI RT_TASK *task; char ulsch_thread_name[64]; #endif int eNB_id = 0, UE_id = 0; PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[eNB_id]; if ((ulsch_thread_index <0) || (ulsch_thread_index>NUMBER_OF_UE_MAX)) { LOG_E(PHY,"[SCHED][ULSCH] Illegal ulsch_thread_index %d!!!!\n",ulsch_thread_index); return 0; } #ifdef RTAI sprintf(ulsch_thread_name,"ULSCH_THREAD%d",ulsch_thread_index); LOG_I(PHY,"[SCHED][ULSCH] starting ulsch_thread %s for process %d\n", ulsch_thread_name, ulsch_thread_index); task = rt_task_init_schmod(nam2num(ulsch_thread_name), 0, 0, 0, SCHED_FIFO, 0xF); if (task==NULL) { LOG_E(PHY,"[SCHED][ULSCH] Problem starting ulsch_thread_index %d!!!!\n",ulsch_thread_index); return 0; } else { LOG_I(PHY,"[SCHED][ULSCH] ulsch_thread for process %d started with id %p\n", ulsch_thread_index, task); } #endif mlockall(MCL_CURRENT | MCL_FUTURE); //rt_set_runnable_on_cpuid(task,1); //cpuid = rtai_cpuid(); #ifdef HARD_RT rt_make_hard_real_time(); #endif //ulsch_cpuid[ulsch_thread_index] = cpuid; while (!oai_exit) { if (pthread_mutex_lock(&ulsch_mutex[ulsch_thread_index]) != 0) { LOG_E(PHY,"[SCHED][ULSCH] error locking mutex.\n"); } else { while (ulsch_instance_cnt[ulsch_thread_index] < 0) { pthread_cond_wait(&ulsch_cond[ulsch_thread_index],&ulsch_mutex[ulsch_thread_index]); } if (pthread_mutex_unlock(&ulsch_mutex[ulsch_thread_index]) != 0) { LOG_E(PHY,"[SCHED][ULSCH] error unlocking mutex.\n"); } } if (oai_exit) break; LOG_D(PHY,"[SCHED][ULSCH] Frame %d: Calling ulsch_decoding with ulsch_thread_index = %d\n",phy_vars_eNB->proc[0].frame_tx,ulsch_thread_index); time_in = rt_get_time_ns(); ulsch_decoding_procedures(ulsch_subframe[ulsch_thread_index]<<1,ulsch_thread_index,phy_vars_eNB,0); time_out = rt_get_time_ns(); if (pthread_mutex_lock(&ulsch_mutex[ulsch_thread_index]) != 0) { msg("[openair][SCHED][ULSCH] error locking mutex.\n"); } else { ulsch_instance_cnt[ulsch_thread_index]--; if (pthread_mutex_unlock(&ulsch_mutex[ulsch_thread_index]) != 0) { msg("[openair][SCHED][ULSCH] error unlocking mutex.\n"); } } } #ifdef HARD_RT rt_make_soft_real_time(); #endif msg("[openair][SCHED][ULSCH] ULSCH thread %d exiting\n",ulsch_thread_index); return 0; }