static void create_thread ( plc_sThread *tp, plc_sProctbl *ptp, plc_sProcess *pp ) { pwr_tStatus sts; long int phase; tp->aref.Objid = ptp->thread; tp->init = ptp->init; tp->exec = ptp->exec; tp->first_scan = 1; tp->PlcThread = pwrb_PlcThread_Init(&sts, tp); tp->csup_lh = csup_Init(&sts, ptp->thread, tp->f_scan_time); tp->i_scan_time = tp->f_scan_time * 1000.0 + 0.5; time_FloatToD(&tp->scan_time, tp->f_scan_time); tp->pp = pp; plc_inittimer(tp); tp->exit = FALSE; link_io_copy_areas(tp); que_Create(&sts, &tp->q_in); que_Create(&sts, &tp->q_out); sts = gdh_ObjidToName(ptp->thread, tp->name, sizeof(tp->name), cdh_mNName); if (EVEN(sts)) { errh_Error("Get name of thread object %s, %m", cdh_ObjidToString(NULL, ptp->thread, 1), sts); return; } sts = gdh_ObjidToPointer(ptp->thread, (void *)&tp->PlcThread); if (EVEN(sts)) { errh_Error("Direct link to thread object \"%s\", %m", tp->name, sts); return; } #if defined OS_LYNX && USE_RT_TIMER sem_init(&tp->ScanSem, 0, 0); tp->ScanMultiple = tp->i_scan_time / (CLK_TCK/1000); tp->IntervalCount = tp->ScanMultiple; #endif sts = thread_Create(&tp->tid, tp->name, (void *(*)())&plc_thread, tp); if (EVEN(sts)) { errh_Error("Creating thread \"%s\", %m", tp->name, sts); return; } /* Wait for thread to initialize. */ phase = (long int)que_Get(&sts, &tp->q_out, NULL, NULL); pwr_Assert(phase == 1); }
static void *mb_connect( void *arg) { io_sRack *rp = (io_sRack *)arg; io_sServerLocal* local = rp->Local; int sts; pwr_sClass_Modbus_TCP_Server *op; struct sockaddr_in r_addr; socklen_t r_addr_len; int c_socket; mb_sCondata *condata; int idx; int found; int i; op = (pwr_sClass_Modbus_TCP_Server *) rp->op; while ( 1) { /* Wait for client connect request */ r_addr_len = sizeof(r_addr); c_socket = accept( local->s, (struct sockaddr *) &r_addr, &r_addr_len); if ( c_socket < 0) { errh_Error( "Error accept IO modbus tcp server %s, %d", rp->Name, local->s); continue; } if ( op->DisableServer) continue; errh_Info( "Connection accepted for IO modbus tcp server %s, %d", rp->Name, c_socket); /* Close other connections to this address */ for ( i = 0; i < MB_MAX_CONNECTIONS; i++) { if ( local->connections[i].occupied && r_addr_len == local->connections[i].addrlen && r_addr.sin_family == local->connections[i].addr.sin_family && memcmp( &r_addr.sin_addr, &local->connections[i].addr.sin_addr, sizeof(r_addr.sin_addr)) == 0) { mb_close_connection( rp, i); } } /* Find next empty in connection list */ found = 0; for ( i = 0; i < MB_MAX_CONNECTIONS; i++) { if ( !local->connections[i].occupied) { found = 1; idx = i; break; } } if ( !found) { /* Remove the oldest connection */ int oldest_idx = 0; for ( i = 1; i < MB_MAX_CONNECTIONS; i++) { if ( time_Acomp( &local->connections[i].last_req_time, &local->connections[oldest_idx].last_req_time) < 0) oldest_idx = i; } mb_close_connection( rp, oldest_idx); errh_Info( "Connection closed, IO modbus tcp server %s, %d", rp->Name, local->s); idx = oldest_idx; } local->connections[idx].c_socket = c_socket; local->connections[idx].occupied = 1; time_GetTime( &local->connections[idx].last_req_time); local->connections[idx].addrlen = r_addr_len; memcpy( &local->connections[idx].addr, &r_addr, r_addr_len); /* Create a thread for this connection */ condata = (mb_sCondata *) malloc( sizeof(mb_sCondata)); condata->rp = rp; condata->idx = idx; sts = thread_Create( &local->connections[idx].t, 0, mb_receive, (void *)condata); if ( EVEN(sts)) { local->connections[idx].occupied = 0; errh_Error( "Error creating thread IO modbus tcp server %s, %d", rp->Name, local->s); free( condata); continue; } } return 0; }