void vegas_sdfits_thread(void *_args) { /* Get args */ struct vegas_thread_args *args = (struct vegas_thread_args *)_args; pthread_cleanup_push((void *)vegas_thread_set_finished, args); /* Set cpu affinity */ int rv = sched_setaffinity(0, sizeof(cpu_set_t), &args->cpuset); if (rv<0) { vegas_error("vegas_sdfits_thread", "Error setting cpu affinity."); perror("sched_setaffinity"); } /* Set priority */ rv=0; if (args->priority != 0) { struct sched_param priority_param; priority_param.sched_priority = args->priority; rv = pthread_setschedparam(pthread_self(), SCHED_FIFO, &priority_param); } if (rv<0) { vegas_error("vegas_sdfits_thread", "Error setting priority level."); perror("set_priority"); } /* Attach to status shared mem area */ struct vegas_status st; rv = vegas_status_attach(&st); if (rv!=VEGAS_OK) { vegas_error("vegas_sdfits_thread", "Error attaching to status shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_status_detach, &st); pthread_cleanup_push((void *)set_exit_status, &st); /* Init status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "init"); vegas_status_unlock_safe(&st); /* Initialize some key parameters */ struct vegas_params gp; struct sdfits sf; sf.data_columns.data = NULL; sf.filenum = 0; sf.new_file = 1; // This is crucial pthread_cleanup_push((void *)vegas_free_sdfits, &sf); pthread_cleanup_push((void *)sdfits_close, &sf); //pf.multifile = 0; // Use a single file for fold mode sf.multifile = 1; // Use a multiple files for fold mode sf.quiet = 0; // Print a message per each subint written /* Attach to databuf shared mem */ struct vegas_databuf *db; db = vegas_databuf_attach(args->input_buffer); if (db==NULL) { vegas_error("vegas_sdfits_thread", "Error attaching to databuf shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db); /* Loop */ int curblock=0, total_status=0, firsttime=1, run=1, got_packet_0=0, dataset=0; char *ptr; char tmpstr[256]; int scan_finished=0, old_filenum; int num_exposures_written = 0; int old_integ_num = -1; signal(SIGINT, cc); do { /* Note waiting status */ vegas_status_lock_safe(&st); if (got_packet_0) sprintf(tmpstr, "waiting(%d)", curblock); else sprintf(tmpstr, "ready"); hputs(st.buf, STATUS_KEY, tmpstr); vegas_status_unlock_safe(&st); /* Wait for buf to have data */ rv = vegas_databuf_wait_filled(db, curblock); if (rv!=0) { // This is a big ol' kludge to avoid this process hanging // due to thread synchronization problems. sleep(1); continue; } /* Note current block */ vegas_status_lock_safe(&st); hputi4(st.buf, "DSKBLKIN", curblock); vegas_status_unlock_safe(&st); /* See how full databuf is */ total_status = vegas_databuf_total_status(db); /* Read param structs for this block */ ptr = vegas_databuf_header(db, curblock); if (firsttime) { vegas_read_obs_params(ptr, &gp, &sf); firsttime = 0; } else { vegas_read_subint_params(ptr, &gp, &sf); } /* Note waiting status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "writing"); vegas_status_unlock_safe(&st); struct sdfits_data_columns* data_cols; struct databuf_index* db_index; db_index = (struct databuf_index*)(vegas_databuf_index(db, curblock)); /* Read the block index, writing each dataset to a SDFITS file */ for(dataset = 0; dataset < db_index->num_datasets; dataset++) { data_cols = (struct sdfits_data_columns*)(vegas_databuf_data(db, curblock) + db_index->disk_buf[dataset].struct_offset); sf.data_columns = *data_cols; /* Write the data */ old_filenum = sf.filenum; sdfits_write_subint(&sf); /*Write new file number to shared memory*/ if(sf.filenum != old_filenum) { vegas_status_lock_safe(&st); hputi4(st.buf, "FILENUM", sf.filenum); vegas_status_unlock_safe(&st); } /* If a new integration number, increment the number of exposures written */ if(data_cols->integ_num != old_integ_num) { num_exposures_written += 1; old_integ_num = data_cols->integ_num; } } /* Indicate number of exposures written */ vegas_status_lock_safe(&st); hputi4(st.buf, "DSKEXPWR", num_exposures_written); vegas_status_unlock_safe(&st); /* For debugging... */ if (gp.drop_frac > 0.0) { printf("Block %d dropped %.3g%% of the packets\n", sf.tot_rows, gp.drop_frac*100.0); } /* Mark as free */ vegas_databuf_set_free(db, curblock); /* Go to next block */ curblock = (curblock + 1) % db->n_block; /* Check for cancel */ pthread_testcancel(); } while (run && !scan_finished); /* Cleanup */ pthread_exit(NULL); pthread_cleanup_pop(0); /* Closes sdfits_close */ pthread_cleanup_pop(0); /* Closes vegas_free_sdfits */ pthread_cleanup_pop(0); /* Closes set_exit_status */ pthread_cleanup_pop(0); /* Closes set_finished */ pthread_cleanup_pop(0); /* Closes vegas_status_detach */ pthread_cleanup_pop(0); /* Closes vegas_databuf_detach */ }
int main(int argc, char *argv[]) { int rv; struct vegas_status s; rv = vegas_status_attach(&s); if (rv!=VEGAS_OK) { fprintf(stderr, "Error connecting to shared mem.\n"); perror(NULL); exit(1); } vegas_status_lock(&s); /* Loop over cmd line to fill in params */ static struct option long_opts[] = { {"key", 1, NULL, 'k'}, {"get", 1, NULL, 'g'}, {"string", 1, NULL, 's'}, {"float", 1, NULL, 'f'}, {"double", 1, NULL, 'd'}, {"int", 1, NULL, 'i'}, {"quiet", 0, NULL, 'q'}, {"clear", 0, NULL, 'C'}, {"del", 0, NULL, 'D'}, {0,0,0,0} }; int opt,opti; char *key=NULL; float flttmp; double dbltmp; int inttmp; int quiet=0, clear=0; while ((opt=getopt_long(argc,argv,"k:g:s:f:d:i:qCD",long_opts,&opti))!=-1) { switch (opt) { case 'k': key = optarg; break; case 'g': hgetr8(s.buf, optarg, &dbltmp); printf("%g\n", dbltmp); break; case 's': if (key) hputs(s.buf, key, optarg); break; case 'f': flttmp = atof(optarg); if (key) hputr4(s.buf, key, flttmp); break; case 'd': dbltmp = atof(optarg); if (key) hputr8(s.buf, key, dbltmp); break; case 'i': inttmp = atoi(optarg); if (key) hputi4(s.buf, key, inttmp); break; case 'D': if (key) hdel(s.buf, key); break; case 'C': clear=1; break; case 'q': quiet=1; break; default: break; } } /* If not quiet, print out buffer */ if (!quiet) { printf(s.buf); printf("\n"); } vegas_status_unlock(&s); if (clear) vegas_status_clear(&s); exit(0); }
int main(int argc, char *argv[]) { static struct option long_opts[] = { {"help", 0, NULL, 'h'}, {0,0,0,0} }; int opt, opti; while ((opt=getopt_long(argc,argv,"h",long_opts,&opti))!=-1) { switch (opt) { default: case 'h': usage(); exit(0); break; } } /* Create FIFO */ int rv = mkfifo(vegas_DAQ_CONTROL, 0666); if (rv!=0 && errno!=EEXIST) { fprintf(stderr, "vegas_daq_server: Error creating control fifo\n"); perror("mkfifo"); exit(1); } /* Open command FIFO for read */ #define MAX_CMD_LEN 1024 char cmd[MAX_CMD_LEN]; int command_fifo; command_fifo = open(vegas_DAQ_CONTROL, O_RDONLY | O_NONBLOCK); if (command_fifo<0) { fprintf(stderr, "vegas_daq_server: Error opening control fifo\n"); perror("open"); exit(1); } /* Attach to shared memory buffers */ struct vegas_status stat; struct vegas_databuf *dbuf_net=NULL, *dbuf_pfb=NULL, *dbuf_acc=NULL; rv = vegas_status_attach(&stat); const int netbuf_id = 1; const int pfbbuf_id = 2; const int accbuf_id = 3; if (rv!=VEGAS_OK) { fprintf(stderr, "Error connecting to vegas_status\n"); exit(1); } dbuf_net = vegas_databuf_attach(netbuf_id); if (dbuf_net==NULL) { fprintf(stderr, "Error connecting to vegas_databuf (raw net)\n"); exit(1); } vegas_databuf_clear(dbuf_net); dbuf_pfb = vegas_databuf_attach(pfbbuf_id); if (dbuf_pfb==NULL) { fprintf(stderr, "Error connecting to vegas_databuf (accum input)\n"); exit(1); } vegas_databuf_clear(dbuf_pfb); dbuf_acc = vegas_databuf_attach(accbuf_id); if (dbuf_acc==NULL) { fprintf(stderr, "Error connecting to vegas_databuf (accum output)\n"); exit(1); } vegas_databuf_clear(dbuf_acc); /* Thread setup */ #define MAX_THREAD 8 int i; int nthread_cur = 0; struct vegas_thread_args args[MAX_THREAD]; pthread_t thread_id[MAX_THREAD]; for (i=0; i<MAX_THREAD; i++) thread_id[i] = 0; /* Print start time for logs */ time_t curtime = time(NULL); char tmp[256]; printf("\nvegas_daq_server started at %s", ctime_r(&curtime,tmp)); fflush(stdout); /* hmm.. keep this old signal stuff?? */ run=1; srv_run=1; signal(SIGINT, srv_cc); signal(SIGTERM, srv_quit); /* Loop over recv'd commands, process them */ int cmd_wait=1; while (cmd_wait && srv_run) { // Check to see if threads have exited, if so, stop them if (check_thread_exit(args, nthread_cur)) { run = 0; stop_threads(args, thread_id, nthread_cur); nthread_cur = 0; } // Heartbeat, status update time_t curtime; char timestr[32]; char *ctmp; time(&curtime); ctime_r(&curtime, timestr); ctmp = strchr(timestr, '\n'); if (ctmp!=NULL) { *ctmp = '\0'; } else { timestr[0]='\0'; } vegas_status_lock(&stat); hputs(stat.buf, "DAQPULSE", timestr); hputs(stat.buf, "DAQSTATE", nthread_cur==0 ? "stopped" : "running"); vegas_status_unlock(&stat); // Flush any status/error/etc for logfiles fflush(stdout); fflush(stderr); // Wait for data on fifo struct pollfd pfd; pfd.fd = command_fifo; pfd.events = POLLIN; rv = poll(&pfd, 1, 1000); if (rv==0) { continue; } else if (rv<0) { if (errno!=EINTR) perror("poll"); continue; } // If we got POLLHUP, it means the other side closed its // connection. Close and reopen the FIFO to clear this // condition. Is there a better/recommended way to do this? if (pfd.revents==POLLHUP) { close(command_fifo); command_fifo = open(vegas_DAQ_CONTROL, O_RDONLY | O_NONBLOCK); if (command_fifo<0) { fprintf(stderr, "vegas_daq_server: Error opening control fifo\n"); perror("open"); break; } continue; } // Read the command memset(cmd, 0, MAX_CMD_LEN); rv = read(command_fifo, cmd, MAX_CMD_LEN-1); if (rv==0) { continue; } else if (rv<0) { if (errno==EAGAIN) { continue; } else { perror("read"); continue; } } // Truncate at newline // TODO: allow multiple commands in one read? char *ptr = strchr(cmd, '\n'); if (ptr!=NULL) *ptr='\0'; // Process the command if (strncasecmp(cmd,"QUIT",MAX_CMD_LEN)==0) { // Exit program printf("Exit\n"); run = 0; stop_threads(args, thread_id, nthread_cur); cmd_wait=0; continue; } else if (strncasecmp(cmd,"START",MAX_CMD_LEN)==0 || strncasecmp(cmd,"MONITOR",MAX_CMD_LEN)==0) { // Start observations // TODO : decide how to behave if observations are running printf("Start observations\n"); if (nthread_cur>0) { printf(" observations already running!\n"); } else { // Figure out which mode to start char obs_mode[32]; if (strncasecmp(cmd,"START",MAX_CMD_LEN)==0) { vegas_status_lock(&stat); vegas_read_obs_mode(stat.buf, obs_mode); vegas_status_unlock(&stat); } else { strncpy(obs_mode, cmd, 32); } printf(" obs_mode = %s\n", obs_mode); // Clear out data bufs vegas_databuf_clear(dbuf_net); vegas_databuf_clear(dbuf_pfb); vegas_databuf_clear(dbuf_acc); // Do it run = 1; if (strncasecmp(obs_mode, "HBW", 4)==0) { hputs(stat.buf, "BW_MODE", "high"); hputs(stat.buf, "SWVER", "1.4"); init_hbw_mode(args, &nthread_cur); start_hbw_mode(args, thread_id); } else if (strncasecmp(obs_mode, "LBW", 4)==0) { hputs(stat.buf, "BW_MODE", "low"); hputs(stat.buf, "SWVER", "1.4"); init_lbw_mode(args, &nthread_cur); start_lbw_mode(args, thread_id); } else if (strncasecmp(obs_mode, "MONITOR", 8)==0) { init_monitor_mode(args, &nthread_cur); start_monitor_mode(args, thread_id); } else { printf(" unrecognized obs_mode!\n"); } } } else if (strncasecmp(cmd,"STOP",MAX_CMD_LEN)==0) { // Stop observations printf("Stop observations\n"); run = 0; stop_threads(args, thread_id, nthread_cur); nthread_cur = 0; } else { // Unknown command printf("Unrecognized command '%s'\n", cmd); } } /* Stop any running threads */ run = 0; stop_threads(args, thread_id, nthread_cur); if (command_fifo>0) close(command_fifo); vegas_status_lock(&stat); hputs(stat.buf, "DAQSTATE", "exiting"); vegas_status_unlock(&stat); curtime = time(NULL); printf("vegas_daq_server exiting cleanly at %s\n", ctime_r(&curtime,tmp)); fflush(stdout); fflush(stderr); /* TODO: remove FIFO */ exit(0); }
/* This thread is passed a single arg, pointer * to the vegas_udp_params struct. This thread should * be cancelled and restarted if any hardware params * change, as this potentially affects packet size, etc. */ void *vegas_net_thread(void *_args) { /* Get arguments */ struct vegas_thread_args *args = (struct vegas_thread_args *)_args; int rv; /* Set cpu affinity */ cpu_set_t cpuset, cpuset_orig; sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig); //CPU_ZERO(&cpuset); CPU_SET(13, &cpuset); rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); if (rv<0) { vegas_error("vegas_net_thread", "Error setting cpu affinity."); perror("sched_setaffinity"); } /* Set priority */ rv = setpriority(PRIO_PROCESS, 0, args->priority); if (rv<0) { vegas_error("vegas_net_thread", "Error setting priority level."); perror("set_priority"); } /* Attach to status shared mem area */ struct vegas_status st; rv = vegas_status_attach(&st); if (rv!=VEGAS_OK) { vegas_error("vegas_net_thread", "Error attaching to status shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_status_detach, &st); pthread_cleanup_push((void *)set_exit_status, &st); /* Init status, read info */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "init"); vegas_status_unlock_safe(&st); /* Read in general parameters */ struct vegas_params gp; struct sdfits pf; char status_buf[VEGAS_STATUS_SIZE]; vegas_status_lock_safe(&st); memcpy(status_buf, st.buf, VEGAS_STATUS_SIZE); vegas_status_unlock_safe(&st); vegas_read_obs_params(status_buf, &gp, &pf); pthread_cleanup_push((void *)vegas_free_sdfits, &pf); /* Read network params */ struct vegas_udp_params up; vegas_read_net_params(status_buf, &up); /* Attach to databuf shared mem */ struct vegas_databuf *db; db = vegas_databuf_attach(args->output_buffer); if (db==NULL) { vegas_error("vegas_net_thread", "Error attaching to databuf shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db); /* Time parameters */ double meas_stt_mjd=0.0; double meas_stt_offs=0.0; /* See which packet format to use */ int nchan=0, npol=0; nchan = pf.hdr.nchan; npol = pf.hdr.npol; /* Figure out size of data in each packet, number of packets * per block, etc. Changing packet size during an obs is not * recommended. */ int block_size; struct vegas_udp_packet p; size_t heap_size, spead_hdr_size; unsigned int heaps_per_block, packets_per_heap; char bw_mode[16]; if (hgets(status_buf, "BW_MODE", 16, bw_mode)) { if(strncmp(bw_mode, "high", 4) == 0) { heap_size = sizeof(struct freq_spead_heap) + nchan*4*sizeof(int); spead_hdr_size = sizeof(struct freq_spead_heap); packets_per_heap = nchan*4*sizeof(int) / PAYLOAD_SIZE; } else if(strncmp(bw_mode, "low", 3) == 0) { heap_size = sizeof(struct time_spead_heap) + PAYLOAD_SIZE; spead_hdr_size = sizeof(struct time_spead_heap); packets_per_heap = 1; } else vegas_error("vegas_net_thread", "Unsupported bandwidth mode"); } else vegas_error("vegas_net_thread", "BW_MODE not set"); if (hgeti4(status_buf, "BLOCSIZE", &block_size)==0) { block_size = db->block_size; hputi4(status_buf, "BLOCSIZE", block_size); } else { if (block_size > db->block_size) { vegas_error("vegas_net_thread", "BLOCSIZE > databuf block_size"); block_size = db->block_size; hputi4(status_buf, "BLOCSIZE", block_size); } } heaps_per_block = (block_size - MAX_HEAPS_PER_BLK*spead_hdr_size) / (heap_size - spead_hdr_size); /* List of databuf blocks currently in use */ unsigned i; const int nblock = 2; struct datablock_stats blocks[nblock]; for (i=0; i<nblock; i++) init_block(&blocks[i], db, heap_size, spead_hdr_size, heaps_per_block); /* Convenience names for first/last blocks in set */ struct datablock_stats *fblock, *lblock; fblock = &blocks[0]; lblock = &blocks[nblock-1]; /* Misc counters, etc */ char *curdata=NULL, *curheader=NULL, *curindex=NULL; unsigned int heap_cntr=0, last_heap_cntr=2048, nextblock_heap_cntr=0; unsigned int heap_offset; unsigned int seq_num=0, last_seq_num=1050; int heap_cntr_diff, seq_num_diff; unsigned int obs_started = 0; unsigned long long npacket_total, npacket_this_block=0, ndropped_total; double drop_frac_avg=0.0; const double drop_lpf = 0.25; prev_heap_cntr = 0; prev_heap_offset = 0; char msg[256]; /* Give all the threads a chance to start before opening network socket */ sleep(1); /* Set up UDP socket */ rv = vegas_udp_init(&up); if (rv!=VEGAS_OK) { vegas_error("vegas_net_thread", "Error opening UDP socket."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_udp_close, &up); /* Main loop */ unsigned force_new_block=0, waiting=-1; signal(SIGINT,cc); while (run) { /* Wait for data */ rv = vegas_udp_wait(&up); if (rv!=VEGAS_OK) { if (rv==VEGAS_TIMEOUT) { /* Set "waiting" flag */ if (waiting!=1) { vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "waiting"); vegas_status_unlock_safe(&st); waiting=1; } continue; } else { vegas_error("vegas_net_thread", "vegas_udp_wait returned error"); perror("vegas_udp_wait"); pthread_exit(NULL); } } /* Read packet */ rv = vegas_udp_recv(&up, &p, bw_mode); if (rv!=VEGAS_OK) { if (rv==VEGAS_ERR_PACKET) { #ifdef DEBUG_NET vegas_warn("vegas_net_thread", "Incorrect pkt size"); #endif continue; } else { vegas_error("vegas_net_thread", "vegas_udp_recv returned error"); perror("vegas_udp_recv"); pthread_exit(NULL); } } /* Update status if needed */ if (waiting!=0) { vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "receiving"); vegas_status_unlock_safe(&st); waiting=0; } /* Check seq num diff */ heap_cntr = vegas_spead_packet_heap_cntr(&p); heap_offset = vegas_spead_packet_heap_offset(&p); seq_num = vegas_spead_packet_seq_num(heap_cntr, heap_offset, packets_per_heap); heap_cntr_diff = heap_cntr - last_heap_cntr; seq_num_diff = (int)(seq_num - last_seq_num); last_seq_num = seq_num; last_heap_cntr = heap_cntr; if (seq_num_diff<=0) { if (seq_num_diff<-1024) { force_new_block=1; obs_started = 1; #ifdef DEBUG_NET printf("Debug: observation started\n"); #endif } else if (seq_num_diff==0) { sprintf(msg, "Received duplicate packet (seq_num=%d)", seq_num); vegas_warn("vegas_net_thread", msg); } else { #ifdef DEBUG_NET sprintf(msg, "out of order packet. Diff = %d", seq_num_diff); vegas_warn("vegas_net_thread", msg); #endif continue; /* No going backwards */ } } else { force_new_block=0; npacket_total += seq_num_diff; ndropped_total += seq_num_diff - 1; npacket_this_block += seq_num_diff; fblock->pkts_dropped += seq_num_diff - 1; #ifdef DEBUG_NET if(seq_num_diff > 1) { sprintf(msg, "Missing packet. seq_num_diff = %d", seq_num_diff); vegas_warn("vegas_net_thread", msg); } #endif } /* If obs has not started, ignore this packet */ if(!obs_started) { fblock->pkts_dropped = 0; npacket_total = 0; ndropped_total = 0; npacket_this_block = 0; continue; } /* Determine if we go to next block */ if (heap_cntr>=nextblock_heap_cntr || force_new_block) { /* Update drop stats */ if (npacket_this_block > 0) drop_frac_avg = (1.0-drop_lpf)*drop_frac_avg + drop_lpf * (double)fblock->pkts_dropped / (double)npacket_this_block; vegas_status_lock_safe(&st); hputi8(st.buf, "NPKT", npacket_total); hputi8(st.buf, "NDROP", ndropped_total); hputr8(st.buf, "DROPAVG", drop_frac_avg); hputr8(st.buf, "DROPTOT", npacket_total ? (double)ndropped_total/(double)npacket_total : 0.0); hputi4(st.buf, "NETBLKOU", fblock->block_idx); vegas_status_unlock_safe(&st); /* Finalize first block, and push it off the list. * Then grab next available block. */ if (fblock->block_idx>=0) finalize_block(fblock); block_stack_push(blocks, nblock); increment_block(lblock, heap_cntr); curdata = vegas_databuf_data(db, lblock->block_idx); curheader = vegas_databuf_header(db, lblock->block_idx); curindex = vegas_databuf_index(db, lblock->block_idx); nextblock_heap_cntr = lblock->heap_idx + heaps_per_block; npacket_this_block = 0; /* If new obs started, reset total counters, get start * time. Start time is rounded to nearest integer * second, with warning if we're off that by more * than 100ms. Any current blocks on the stack * are also finalized/reset */ if (force_new_block) { /* Reset stats */ npacket_total=0; ndropped_total=0; npacket_this_block = 0; /* Get obs start time */ get_current_mjd_double(&meas_stt_mjd); printf("vegas_net_thread: got start packet at MJD %f", meas_stt_mjd); meas_stt_offs = meas_stt_mjd*24*60*60 - floor(meas_stt_mjd*24*60*60); if(meas_stt_offs > 0.1 && meas_stt_offs < 0.9) { char msg[256]; sprintf(msg, "Second fraction = %3.1f ms > +/-100 ms", meas_stt_offs*1e3); vegas_warn("vegas_net_thread", msg); } vegas_status_lock_safe(&st); hputnr8(st.buf, "M_STTMJD", 8, meas_stt_mjd); hputr8(st.buf, "M_STTOFF", meas_stt_offs); vegas_status_unlock_safe(&st); /* Warn if 1st packet number is not zero */ if (seq_num!=0) { char msg[256]; sprintf(msg, "First packet number is not 0 (seq_num=%d)", seq_num); vegas_warn("vegas_net_thread", msg); } } /* Read current status shared mem */ vegas_status_lock_safe(&st); memcpy(status_buf, st.buf, VEGAS_STATUS_SIZE); vegas_status_unlock_safe(&st); /* Wait for new block to be free, then clear it * if necessary and fill its header with new values. */ while ((rv=vegas_databuf_wait_free(db, lblock->block_idx)) != VEGAS_OK) { if (rv==VEGAS_TIMEOUT) { waiting=1; vegas_warn("vegas_net_thread", "timeout while waiting for output block\n"); vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "blocked"); vegas_status_unlock_safe(&st); continue; } else { vegas_error("vegas_net_thread", "error waiting for free databuf"); run=0; pthread_exit(NULL); break; } } memcpy(curheader, status_buf, VEGAS_STATUS_SIZE); memset(curdata, 0, block_size); memset(curindex, 0, db->index_size); } /* Copy packet into any blocks where it belongs. * The "write packets" functions also update drop stats * for blocks, etc. */ int nblocks = 0; for (i=0; i<nblock; i++) { if ((blocks[i].block_idx>=0) && (block_heap_check(&blocks[i],heap_cntr)==0)) { if (nblocks > 0) { printf("vegas_net_thread: Warning! Adding packet to more than one block! heap_cntr= %d, block = %d",heap_cntr,i); } nblocks++; write_spead_packet_to_block(&blocks[i], &p, heap_cntr, heap_offset, packets_per_heap, bw_mode); } } /* Will exit if thread has been cancelled */ pthread_testcancel(); } pthread_exit(NULL); /* Have to close all push's */ pthread_cleanup_pop(0); /* Closes push(vegas_udp_close) */ pthread_cleanup_pop(0); /* Closes set_exit_status */ pthread_cleanup_pop(0); /* Closes vegas_free_psrfits */ pthread_cleanup_pop(0); /* Closes vegas_status_detach */ pthread_cleanup_pop(0); /* Closes vegas_databuf_detach */ }
void vegas_null_thread(void *_args) { int rv; /* Set cpu affinity */ cpu_set_t cpuset, cpuset_orig; sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig); CPU_ZERO(&cpuset); CPU_SET(6, &cpuset); rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); if (rv<0) { vegas_error("vegas_null_thread", "Error setting cpu affinity."); perror("sched_setaffinity"); } /* Set priority */ rv = setpriority(PRIO_PROCESS, 0, 0); if (rv<0) { vegas_error("vegas_null_thread", "Error setting priority level."); perror("set_priority"); } /* Get args */ struct vegas_thread_args *args = (struct vegas_thread_args *)_args; /* Attach to status shared mem area */ struct vegas_status st; rv = vegas_status_attach(&st); if (rv!=VEGAS_OK) { vegas_error("vegas_null_thread", "Error attaching to status shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_status_detach, &st); pthread_cleanup_push((void *)set_exit_status, &st); /* Init status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "init"); vegas_status_unlock_safe(&st); /* Attach to databuf shared mem */ struct vegas_databuf *db; db = vegas_databuf_attach(args->input_buffer); if (db==NULL) { vegas_error("vegas_null_thread", "Error attaching to databuf shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db); /* Loop */ char *ptr; struct vegas_params gp; #if FITS_TYPE == PSRFITS struct psrfits pf; pf.sub.dat_freqs = NULL; pf.sub.dat_weights = NULL; pf.sub.dat_offsets = NULL; pf.sub.dat_scales = NULL; pthread_cleanup_push((void *)vegas_free_psrfits, &pf); #else struct sdfits pf; pthread_cleanup_push((void *)vegas_free_sdfits, &pf); #endif int curblock=0; signal(SIGINT,cc); while (run) { /* Note waiting status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "waiting"); vegas_status_unlock_safe(&st); /* Wait for buf to have data */ rv = vegas_databuf_wait_filled(db, curblock); if (rv!=0) { //sleep(1); continue; } /* Note waiting status, current block */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "discarding"); hputi4(st.buf, "DSKBLKIN", curblock); vegas_status_unlock_safe(&st); /* Get params */ ptr = vegas_databuf_header(db, curblock); vegas_read_obs_params(ptr, &gp, &pf); /* Output if data was lost */ #if FITS_TYPE == PSRFITS if (gp.n_dropped!=0 && (gp.packetindex==0 || strcmp(pf.hdr.obs_mode,"SEARCH"))) { printf("Block beginning with pktidx=%lld dropped %d packets\n", gp.packetindex, gp.n_dropped); fflush(stdout); } #else if (gp.num_pkts_dropped!=0 && gp.num_pkts_rcvd!=0) { printf("Block received %d packets and dropped %d packets\n", gp.num_pkts_rcvd, gp.num_pkts_dropped); fflush(stdout); } #endif /* Mark as free */ vegas_databuf_set_free(db, curblock); /* Go to next block */ curblock = (curblock + 1) % db->n_block; /* Check for cancel */ pthread_testcancel(); } pthread_exit(NULL); pthread_cleanup_pop(0); /* Closes set_exit_status */ pthread_cleanup_pop(0); /* Closes vegas_free_psrfits */ pthread_cleanup_pop(0); /* Closes vegas_status_detach */ pthread_cleanup_pop(0); /* Closes vegas_databuf_detach */ }
void vegas_rawdisk_thread(void *_args) { /* Set cpu affinity */ cpu_set_t cpuset, cpuset_orig; sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig); CPU_ZERO(&cpuset); CPU_SET(6, &cpuset); int rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); if (rv<0) { vegas_error("vegas_rawdisk_thread", "Error setting cpu affinity."); perror("sched_setaffinity"); } /* Get args */ struct vegas_thread_args *args = (struct vegas_thread_args *)_args; /* Set priority */ rv = setpriority(PRIO_PROCESS, 0, 0); if (rv<0) { vegas_error("vegas_rawdisk_thread", "Error setting priority level."); perror("set_priority"); } /* Attach to status shared mem area */ struct vegas_status st; rv = vegas_status_attach(&st); if (rv!=VEGAS_OK) { vegas_error("vegas_rawdisk_thread", "Error attaching to status shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_status_detach, &st); pthread_cleanup_push((void *)set_exit_status, &st); /* Init status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "init"); vegas_status_unlock_safe(&st); /* Read in general parameters */ struct vegas_params gp; struct sdfits sf; pthread_cleanup_push((void *)vegas_free_sdfits, &sf); /* Attach to databuf shared mem */ struct vegas_databuf *db; db = vegas_databuf_attach(args->input_buffer); if (db==NULL) { vegas_error("vegas_rawdisk_thread", "Error attaching to databuf shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db); /* Init output file */ FILE *fraw = NULL; pthread_cleanup_push((void *)safe_fclose, fraw); /* Loop */ int blocksize=0; int curblock=0, dataset; int block_count=0, blocks_per_file=128, filenum=0; int first=1; char *ptr; float *data_array; struct databuf_index* db_index; signal(SIGINT,cc); while (run) { /* Note waiting status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "waiting"); vegas_status_unlock_safe(&st); /* Wait for buf to have data */ rv = vegas_databuf_wait_filled(db, curblock); if (rv!=0) continue; /* Read param struct and index for this block */ ptr = vegas_databuf_header(db, curblock); db_index = (struct databuf_index*)(vegas_databuf_index(db, curblock)); /* If first time running */ if (first==1) { first = 0; vegas_read_obs_params(ptr, &gp, &sf); char fname[256]; sprintf(fname, "%s_%4d.raw", sf.basefilename, filenum); fprintf(stderr, "Opening raw file '%s'\n", fname); // TODO: check for file exist. fraw = fopen(fname, "wb"); if (fraw==NULL) { vegas_error("vegas_rawdisk_thread", "Error opening file."); pthread_exit(NULL); } } else vegas_read_subint_params(ptr, &gp, &sf); /* See if we need to open next file */ if (block_count >= blocks_per_file) { fclose(fraw); filenum++; char fname[256]; sprintf(fname, "%s_%4d.raw", sf.basefilename, filenum); fprintf(stderr, "Opening raw file '%s'\n", fname); fraw = fopen(fname, "wb"); if (fraw==NULL) { vegas_error("vegas_rawdisk_thread", "Error opening file."); pthread_exit(NULL); } block_count=0; } /* Get full data block size */ hgeti4(ptr, "BLOCSIZE", &blocksize); /* Note writing status and current block */ vegas_status_lock_safe(&st); hputi4(st.buf, "DSKBLKIN", curblock); hputs(st.buf, STATUS_KEY, "writing"); vegas_status_unlock_safe(&st); /* Write all data arrays to disk */ for(dataset = 0; dataset < db_index->num_datasets; dataset++) { data_array = (float*)(vegas_databuf_data(db, curblock) + db_index->disk_buf[dataset].array_offset); rv = fwrite(data_array, 4, (size_t)(db_index->array_size/4), fraw); if (rv != db_index->array_size/4) { vegas_error("vegas_rawdisk_thread", "Error writing data."); } } /* Increment block counter */ block_count++; /* flush output */ fflush(fraw); /* Mark as free */ vegas_databuf_set_free(db, curblock); /* Go to next block */ curblock = (curblock + 1) % db->n_block; /* Check for cancel */ pthread_testcancel(); } pthread_exit(NULL); pthread_cleanup_pop(0); /* Closes fclose */ pthread_cleanup_pop(0); /* Closes vegas_databuf_detach */ pthread_cleanup_pop(0); /* Closes vegas_free_psrfits */ pthread_cleanup_pop(0); /* Closes set_exit_status */ pthread_cleanup_pop(0); /* Closes vegas_status_detach */ }
int main(int argc, char *argv[]) { static struct option long_opts[] = { {"help", 0, NULL, 'h'}, {"disk", 0, NULL, 'd'}, {"only_net",0, NULL, 'o'}, {0,0,0,0} }; int opt, opti; int disk=0, only_net=0; while ((opt=getopt_long(argc,argv,"hdo",long_opts,&opti))!=-1) { switch (opt) { case 'd': disk=1; break; case 'o': only_net=1; break; default: case 'h': usage(); exit(0); break; } } /* Net thread args */ struct vegas_thread_args net_args; vegas_thread_args_init(&net_args); net_args.output_buffer = 1; /* Init shared mem */ struct vegas_status stat; struct vegas_databuf *dbuf=NULL; int rv = vegas_status_attach(&stat); if (rv!=VEGAS_OK) { fprintf(stderr, "Error connecting to vegas_status\n"); exit(1); } dbuf = vegas_databuf_attach(net_args.output_buffer); /* If attach fails, first try to create the databuf */ if (dbuf==NULL) #ifdef NEW_GBT dbuf = vegas_databuf_create(24, 32*1024*1024, net_args.output_buffer, CPU_INPUT_BUF); #else dbuf = vegas_databuf_create(24, 32*1024*1024, net_args.output_buffer); #endif /* If that also fails, exit */ if (dbuf==NULL) { fprintf(stderr, "Error connecting to vegas_databuf\n"); exit(1); } vegas_databuf_clear(dbuf); run=1; signal(SIGINT, cc); /* Launch net thread */ pthread_t net_thread_id; rv = pthread_create(&net_thread_id, NULL, vegas_net_thread, (void *)&net_args); if (rv) { fprintf(stderr, "Error creating net thread.\n"); perror("pthread_create"); exit(1); } /* Launch raw disk (or null) thread */ struct vegas_thread_args null_args; vegas_thread_args_init(&null_args); null_args.input_buffer = net_args.output_buffer; pthread_t disk_thread_id=0; if (only_net==0) { if (disk) rv = pthread_create(&disk_thread_id, NULL, vegas_rawdisk_thread, (void *)&null_args); else rv = pthread_create(&disk_thread_id, NULL, vegas_null_thread, (void *)&null_args); if (rv) { fprintf(stderr, "Error creating null thread.\n"); perror("pthread_create"); exit(1); } } /* Wait for end */ while (run) { sleep(1); } if (disk_thread_id) pthread_cancel(disk_thread_id); pthread_cancel(net_thread_id); if (disk_thread_id) pthread_kill(disk_thread_id,SIGINT); pthread_kill(net_thread_id,SIGINT); pthread_join(net_thread_id,NULL); printf("Joined net thread\n"); fflush(stdout); fflush(stderr); if (disk_thread_id) { pthread_join(disk_thread_id,NULL); printf("Joined disk thread\n"); fflush(stdout); fflush(stderr); } vegas_thread_args_destroy(&null_args); exit(0); }
int main(int argc, char *argv[]) { /* thread args */ struct vegas_thread_args net_args, pfb_args, accum_args, disk_args; vegas_thread_args_init(&net_args); vegas_thread_args_init(&pfb_args); vegas_thread_args_init(&accum_args); vegas_thread_args_init(&disk_args); net_args.output_buffer = 1; pfb_args.input_buffer = net_args.output_buffer; pfb_args.output_buffer = 2; accum_args.input_buffer = pfb_args.output_buffer; accum_args.output_buffer = 3; disk_args.input_buffer = accum_args.output_buffer; /* Init status shared mem */ struct vegas_status stat; int rv = vegas_status_attach(&stat); if (rv!=VEGAS_OK) { fprintf(stderr, "Error connecting to vegas_status\n"); exit(1); } hputs(stat.buf, "BW_MODE", "low"); hputs(stat.buf, "SWVER", SWVER); /* Init first shared data buffer */ struct vegas_databuf *gpu_input_dbuf=NULL; gpu_input_dbuf = vegas_databuf_attach(pfb_args.input_buffer); /* If attach fails, first try to create the databuf */ if (gpu_input_dbuf==NULL) gpu_input_dbuf = vegas_databuf_create(24, 32*1024*1024, pfb_args.input_buffer, GPU_INPUT_BUF); /* If that also fails, exit */ if (gpu_input_dbuf==NULL) { fprintf(stderr, "Error connecting to gpu_input_dbuf\n"); exit(1); } vegas_databuf_clear(gpu_input_dbuf); /* Init second shared data buffer */ struct vegas_databuf *cpu_input_dbuf=NULL; cpu_input_dbuf = vegas_databuf_attach(accum_args.input_buffer); /* If attach fails, first try to create the databuf */ if (cpu_input_dbuf==NULL) cpu_input_dbuf = vegas_databuf_create(24, 32*1024*1024, accum_args.input_buffer, CPU_INPUT_BUF); /* If that also fails, exit */ if (cpu_input_dbuf==NULL) { fprintf(stderr, "Error connecting to cpu_input_dbuf\n"); exit(1); } vegas_databuf_clear(cpu_input_dbuf); /* Init third shared data buffer */ struct vegas_databuf *disk_input_dbuf=NULL; disk_input_dbuf = vegas_databuf_attach(disk_args.input_buffer); /* If attach fails, first try to create the databuf */ if (disk_input_dbuf==NULL) disk_input_dbuf = vegas_databuf_create(16, 16*1024*1024, disk_args.input_buffer, DISK_INPUT_BUF); /* If that also fails, exit */ if (disk_input_dbuf==NULL) { fprintf(stderr, "Error connecting to disk_input_dbuf\n"); exit(1); } /* Resize the blocks in the disk input buffer, based on the exposure parameter */ struct vegas_params vegas_p; struct sdfits sf; vegas_read_obs_params(stat.buf, &vegas_p, &sf); vegas_read_subint_params(stat.buf, &vegas_p, &sf); long long int num_exp_per_blk = (int)(ceil(DISK_WRITE_INTERVAL / sf.data_columns.exposure)); long long int disk_block_size = num_exp_per_blk * (sf.hdr.nchan * sf.hdr.nsubband * 4 * 4); disk_block_size = disk_block_size > (long long int)(32*1024*1024) ? (long long int)(32*1024*1024) : disk_block_size; vegas_conf_databuf_size(disk_input_dbuf, disk_block_size); vegas_databuf_clear(disk_input_dbuf); signal(SIGINT, cc); /* Launch net thread */ pthread_t net_thread_id; #ifdef FAKE_NET rv = pthread_create(&net_thread_id, NULL, vegas_fake_net_thread, (void *)&net_args); #else rv = pthread_create(&net_thread_id, NULL, vegas_net_thread, (void *)&net_args); #endif if (rv) { fprintf(stderr, "Error creating net thread.\n"); perror("pthread_create"); exit(1); } /* Launch PFB thread */ pthread_t pfb_thread_id; rv = pthread_create(&pfb_thread_id, NULL, vegas_pfb_thread, (void *)&pfb_args); if (rv) { fprintf(stderr, "Error creating PFB thread.\n"); perror("pthread_create"); exit(1); } /* Launch accumulator thread */ pthread_t accum_thread_id; rv = pthread_create(&accum_thread_id, NULL, vegas_accum_thread, (void *)&accum_args); if (rv) { fprintf(stderr, "Error creating accumulator thread.\n"); perror("pthread_create"); exit(1); } /* Launch RAW_DISK thread, SDFITS disk thread, or PSRFITS disk thread */ pthread_t disk_thread_id; #ifdef RAW_DISK rv = pthread_create(&disk_thread_id, NULL, vegas_rawdisk_thread, (void *)&disk_args); #elif defined NULL_DISK rv = pthread_create(&disk_thread_id, NULL, vegas_null_thread, (void *)&disk_args); #elif defined EXT_DISK rv = 0; #elif FITS_TYPE == PSRFITS rv = pthread_create(&disk_thread_id, NULL, vegas_psrfits_thread, (void *)&disk_args); #elif FITS_TYPE == SDFITS rv = pthread_create(&disk_thread_id, NULL, vegas_sdfits_thread, (void *)&disk_args); #endif if (rv) { fprintf(stderr, "Error creating disk thread.\n"); perror("pthread_create"); exit(1); } /* Wait for end */ run=1; while (run) { sleep(1); if (disk_args.finished) run=0; } #ifndef EXT_DISK pthread_cancel(disk_thread_id); #endif pthread_cancel(pfb_thread_id); pthread_cancel(accum_thread_id); pthread_cancel(net_thread_id); #ifndef EXT_DISK pthread_kill(disk_thread_id,SIGINT); #endif pthread_kill(accum_thread_id,SIGINT); pthread_kill(pfb_thread_id,SIGINT); pthread_kill(net_thread_id,SIGINT); pthread_join(net_thread_id,NULL); printf("Joined net thread\n"); fflush(stdout); pthread_join(pfb_thread_id,NULL); printf("Joined PFB thread\n"); fflush(stdout); pthread_join(accum_thread_id,NULL); printf("Joined accumulator thread\n"); fflush(stdout); #ifndef EXT_DISK pthread_join(disk_thread_id,NULL); printf("Joined disk thread\n"); fflush(stdout); #endif vegas_thread_args_destroy(&net_args); vegas_thread_args_destroy(&pfb_args); vegas_thread_args_destroy(&accum_args); vegas_thread_args_destroy(&disk_args); exit(0); }
void vegas_pfb_thread(void *_args) { /* Get args */ struct vegas_thread_args *args = (struct vegas_thread_args *)_args; int rv; /* Set cpu affinity */ cpu_set_t cpuset, cpuset_orig; sched_getaffinity(0, sizeof(cpu_set_t), &cpuset_orig); //CPU_ZERO(&cpuset); CPU_CLR(13, &cpuset); CPU_SET(11, &cpuset); rv = sched_setaffinity(0, sizeof(cpu_set_t), &cpuset); if (rv<0) { vegas_error("vegas_pfb_thread", "Error setting cpu affinity."); perror("sched_setaffinity"); } /* Set priority */ rv = setpriority(PRIO_PROCESS, 0, args->priority); if (rv<0) { vegas_error("vegas_pfb_thread", "Error setting priority level."); perror("set_priority"); } /* Attach to status shared mem area */ struct vegas_status st; rv = vegas_status_attach(&st); if (rv!=VEGAS_OK) { vegas_error("vegas_pfb_thread", "Error attaching to status shared memory."); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_status_detach, &st); pthread_cleanup_push((void *)set_exit_status, &st); pthread_cleanup_push((void *)vegas_thread_set_finished, args); /* Init status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "init"); vegas_status_unlock_safe(&st); /* Init structs */ struct vegas_params gp; struct sdfits sf; pthread_cleanup_push((void *)vegas_free_sdfits, &sf); /* Attach to databuf shared mem */ struct vegas_databuf *db_in, *db_out; db_in = vegas_databuf_attach(args->input_buffer); if (db_in==NULL) { char msg[256]; sprintf(msg, "Error attaching to databuf(%d) shared memory.", args->input_buffer); vegas_error("vegas_pfb_thread", msg); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db_in); db_out = vegas_databuf_attach(args->output_buffer); if (db_out==NULL) { char msg[256]; sprintf(msg, "Error attaching to databuf(%d) shared memory.", args->output_buffer); vegas_error("vegas_pfb_thread", msg); pthread_exit(NULL); } pthread_cleanup_push((void *)vegas_databuf_detach, db_out); /* Loop */ char *hdr_in = NULL; int curblock_in=0; int first=1; int acc_len = 0; int nchan = 0; int nsubband = 0; signal(SIGINT,cc); vegas_status_lock_safe(&st); if (hgeti4(st.buf, "NCHAN", &nchan)==0) { fprintf(stderr, "ERROR: %s not in status shm!\n", "NCHAN"); } if (hgeti4(st.buf, "NSUBBAND", &nsubband)==0) { fprintf(stderr, "ERROR: %s not in status shm!\n", "NSUBBAND"); } vegas_status_unlock_safe(&st); if (EXIT_SUCCESS != init_gpu(db_in->block_size, db_out->block_size, nsubband, nchan)) { (void) fprintf(stderr, "ERROR: GPU initialisation failed!\n"); run = 0; } while (run) { /* Note waiting status */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "waiting"); vegas_status_unlock_safe(&st); /* Wait for buf to have data */ rv = vegas_databuf_wait_filled(db_in, curblock_in); if (rv!=0) continue; /* Note waiting status, current input block */ vegas_status_lock_safe(&st); hputs(st.buf, STATUS_KEY, "processing"); hputi4(st.buf, "PFBBLKIN", curblock_in); vegas_status_unlock_safe(&st); hdr_in = vegas_databuf_header(db_in, curblock_in); /* Get params */ if (first) { vegas_read_obs_params(hdr_in, &gp, &sf); /* Read required exposure from status shared memory, and calculate corresponding accumulation length */ acc_len = (abs(sf.hdr.chan_bw) * sf.hdr.hwexposr); } vegas_read_subint_params(hdr_in, &gp, &sf); /* Call PFB function */ do_pfb(db_in, curblock_in, db_out, first, st, acc_len); /* Mark input block as free */ vegas_databuf_set_free(db_in, curblock_in); /* Go to next input block */ curblock_in = (curblock_in + 1) % db_in->n_block; /* Check for cancel */ pthread_testcancel(); if (first) { first=0; } } run=0; //cudaThreadExit(); pthread_exit(NULL); cleanup_gpu(); pthread_cleanup_pop(0); /* Closes vegas_databuf_detach(out) */ pthread_cleanup_pop(0); /* Closes vegas_databuf_detach(in) */ pthread_cleanup_pop(0); /* Closes vegas_free_sdfits */ pthread_cleanup_pop(0); /* Closes vegas_thread_set_finished */ pthread_cleanup_pop(0); /* Closes set_exit_status */ pthread_cleanup_pop(0); /* Closes vegas_status_detach */ }