> > *I know the feeling.* > > * Good luck and don't hesitate to ask for more help, or at least advice,* > * for whatever I can do. Linux I can't really talk about, the* > * fundamentals I think I can.* >
I think Linux in this context was not so important. I mean it is / was, but I generally do ok with high level on topic discussions. So long as I know what my options are, everything is good. *Ask either on the list or private email if you want.* > I don't mind asking here if that is fine with everyone. Technically, I felt a little funny posting here, as it was semi off topic( in relation to the beaglebone ), but maybe the discussion helps someone else too ? If there is a problem, then I have no issues moving to another forum. On Mon, Aug 24, 2015 at 6:00 PM, Harvey White <[email protected]> wrote: > On Mon, 24 Aug 2015 17:40:33 -0700, you wrote: > > >Hey Harvey, and Walter > > > >Just kind of an update. Last night after our discussion I found a really > >good resource / discussion of what fork() is and the different ways it can > >be used. So with this information in mind along with our discussion > >yesterday it seems that what I want to do can indeed be done without using > >POSIX shared memory( I had little doubt ) - *and* seemingly more simple. > > That sounds good > > > >I'd still have to use a Semaphore - I think to keep the web server > callback > >from stalling my canbus routines. But I think that seems fairly > reasonable. > > > > That also sounds quite reasonable to do. As your programs get more > complicated, you'll have to figure out how to interlock/protect/manage > resources. > > I have a project that manages a graphics engine (software), I2C slave > (ditto), heartbeat/errortask, I2C error reporting task, and the like; > and uses a FIFO, semaphores, queues and the like to protect resources > and manage memory. > > Probably a bit too complex, but it kinda grew that way. > > > >Still I may just implement semaphores into my current code to check it > out, > >but not sure when. Been a semi rough day, and I'm whooped . . . > > I know the feeling. > > Good luck and don't hesitate to ask for more help, or at least advice, > for whatever I can do. Linux I can't really talk about, the > fundamentals I think I can. > > Ask either on the list or private email if you want. > > Harvey > > > > >On Sun, Aug 23, 2015 at 9:44 PM, William Hermans <[email protected]> > wrote: > > > >> OK have a good one, thanks for the discussion. > >> > >> On Sun, Aug 23, 2015 at 9:11 PM, Harvey White <[email protected]> > >> wrote: > >> > >>> On Sun, 23 Aug 2015 20:18:26 -0700 (PDT), you wrote: > >>> > >>> > > >>> >> > >>> >> *Well, you're certainly right that the callback is messing* > >>> >> * things up. If I assume the same callback, then the callback is* > >>> >> * certainly changing data. If you can set the right breakpoint, you > >>> can* > >>> >> * tag the situation *if* the breakpoint also knows that the process > is* > >>> >> * reading from the CAN bus.* > >>> >> > >>> >> * Had you considered disabling that callback function until the > read* > >>> >> * from the CANbus is finished? Would it be practical? That's where > >>> the* > >>> >> * semaphore might help a lot.* > >>> >> > >>> >> * what variables could be common between the two routines?* > >>> >> > >>> >> * Harvey* > >>> >> > >>> > > >>> >Well this is where previous experience fails me. I've pretty much > avoided > >>> >code related to threading in software. In the past. I do know of > fork() > >>> and > >>> >roughly what it is capable of, and I know about threads, but not to > >>> >implement them in C on Linux. Or what can be done with them. Lets talk > >>> code > >>> >a minute. > >>> > >>> OK, as well as I can follow it. > >>> > >>> > > >>> >*IPC - Server - Reads from canbus* > >>> >int main(){ > >>> > struct can_frame frame; > >>> > int sock = InitializeCAN("vcan0"); > >>> > > >>> > statistics_t *stats = NULL; > >>> > > >>> > const long shm_size = sysconf(_SC_PAGESIZE); > >>> > > >>> > int shm_fd = shm_open("acme", O_CREAT | O_RDWR, FILE_PERMS); > >>> > >>> **NOTE: the problem may be "acme", since we know that acme products > >>> are not effective against roadrunners..... > >>> > >>> > if(shm_fd == -1) > >>> > HandleError(strerror(errno)); > >>> > > >>> > const int retval = ftruncate(shm_fd, shm_size); > >>> > if(retval == -1) > >>> > HandleError(strerror(errno)); > >>> > > >>> > shared_memory = InitializeShm(shm_size * sizeof(char), shm_fd); > >>> > close(shm_fd); > >>> > > >>> > while(1){ > >>> > frame = ReadFrame(sock); > >>> > if(frame.can_dlc == FRAME_DLC) > >>> > stats = ProcessFastpacket(frame); > >>> > >>> right at this point, you have no protection against access and no > >>> interlocking. > >>> > >>> I'll have to give you pseudocode, because I don't know how to do this > >>> in Linux. > >>> > >>> In the init routine, before you set up either main as a > >>> process (I assume you do this). Declare a semaphore: > >>> > >>> semaphore_handle shared_access; // create semaphore > >>> handle accessible to both processes. > >>> semaphore_create (shared_access); // create > >>> semaphore > >>> > >>> > >>> then modify this next section to: > >>> > >>> if(stats != NULL){ > >>> if (semaphore_take(shared_access), <wait forever>) > >>> { > >>> WriteToShm(shared_memory, stats); > >>> semaphore_give (shared_access); > >>> } > >>> stats = NULL; > >>> printf("%s", ReadFromShm(shared_memory)); > >>> } > >>> task_delay(n); > >>> > >>> NOTE: Process A hangs until it can "get" the semaphore; if Process B > >>> has it, B can keep it only long enough to send the packet > >>> > > >>> > if(stats != NULL){ > >>> > WriteToShm(shared_memory, stats); > >>> > stats = NULL; > >>> > printf("%s", ReadFromShm(shared_memory)); > >>> > } > >>> > } > >>> >}/* main() */ > >>> > > >>> > > >>> > > >>> >*IPC - Client / webserver* > >>> > > >>> >int main(void) { > >>> > struct mg_server *server = mg_create_server(NULL, ev_handler); > >>> > > >>> > mg_set_option(server, "listening_port", "8000"); > >>> > mg_set_option(server, "document_root", "./web"); > >>> > > >>> > printf("Started on port %s\n", mg_get_option(server, > >>> >"listening_port")); > >>> > > >>> > // POSIX IPC - shared memory > >>> > const long shm_size = sysconf(_SC_PAGESIZE); > >>> > int shm_fd = shm_open("file", O_CREAT | O_RDWR, FILE_PERMS); > >>> > if(shm_fd == -1) > >>> > HandleError(strerror(errno)); > >>> > > >>> > const int retval = ftruncate(shm_fd, shm_size); > >>> > if(retval == -1) > >>> > HandleError(strerror(errno)); > >>> > > >>> > shared_memory = InitializeShm(shm_size * sizeof(char), > shm_fd); > >>> > > >>> > close(shm_fd); > >>> > > >>> > char id = 0x00; > >>> > for (;;) { > >>> > mg_poll_server(server, 10); > >>> > > >>> then do the same here > >>> > >>> if (semaphore_take(shared_access), <wait forever>) > >>> { > >>> if(shared_memory->sdata.data[19] != id){ > >>> push_message(server,shared_memory->sdata.data); > >>> id = > >>> shared_memory->sdata.data[19]; > >>> } > >>> semaphore_give (shared_access); > >>> } > >>> task_delay (n clock ticks); > >>> > >>> semaphore_take gets the semaphore if and only if it's available. It > >>> does so in a thread safe manner. the <wait_forever> is whatever value > >>> the system uses to tell the process to hang. You don't want the > >>> process to wait and then just go. > >>> > >>> Because each example here releases the semaphore (semaphore_give) if > >>> and only if it could get it, and since giving and taking the semaphore > >>> is thread safe, the two threads should be fine. > >>> > >>> So your "consumer" thread can't check for valid data until there's > >>> something there. When it first starts up, it has to get bad (null) > >>> data and throw that away, since you can't guarantee that one thread > >>> starts before the other (unless you block the thread using a suspend, > >>> but that's not really the best thing to do), so you have to consider > >>> that you have two parallel and independent threads. > >>> > >>> The consumer thread can access shared memory only when it's not been > >>> actively written to. It has to figure out if data is good and what to > >>> do with it. However, once written, that data will remain uncorrupted > >>> until the consumer has read and processed it (because the consumer has > >>> the semaphore and doesn't give it up until then). > >>> > >>> The producer thread checks to see if the data is there to send, > >>> accesses shared memory by getting the semaphore (when the consumer is > >>> not reading it), and then writes that shared memory. It then releases > >>> the semaphore, goes idle (because the task switcher has to have a time > >>> to start up the other task unless you have multiple cores), and then > >>> checks for data, and waits to see when it can write that data. > >>> > >>> The typical task clock is either 1 ms or 10 ms, and the clock tick is > >>> that (1 ms or 10 ms per tick). You play with the values for best > >>> throughput on the n delays. > >>> > >>> > >>> > if(shared_memory->sdata.data[19] != id){ > >>> > push_message(server, > shared_memory->sdata.data); > >>> > id = shared_memory->sdata.data[19]; > >>> > } > >>> > } > >>> > > >>> > mg_destroy_server(&server); > >>> > return 0; > >>> >} > >>> > > >>> >In the context of whats interesting where threading is concerned. The > >>> loops > >>> >in each executable here might be useful. If somehow each, or even just > >>> the > >>> >for loop in the IPC client could somehow use objects in memory from > the > >>> IPC > >>> >server. > >>> > >>> That was the shared memory, right? > >>> > >>> >That is let us suppose for a minute IPC was removed entirely, then > >>> >somehow I could turn off the callback in the IPC client. This is what > I'm > >>> >having a problem imagining. How could this be done ? > >>> > >>> You may possibly be able to schedule *when* the callback happens. > >>> > >>> What causes the callback, sending a CAN message? > >>> > >>> > In the context of > >>> >libmongoose I'm not sure. In the context of threading or using fork() > I'm > >>> >also not sure. > >>> > >>> Fork creates a separate process which can be controlled or killed as > >>> needed, running as a sub-process (IIRC). > >>> > >>> you're dealing with creating two processes (really two programs) and > >>> interprocess communication. > >>> > >>> >But if I could somehow through using threading context to > >>> >disable the callback I think that would be ideal. That way I could > simply > >>> >disable that whole thread for a fraction of a second, and then resume > it > >>> >once a fastpacket is constructed. > >>> > >>> > >>> > >>> Well, synchronizing the two tasks with semaphores says that if the > >>> callback happens and you can turn off that callback, then the data is > >>> ok as long as you can schedule the callback. No idea when that > >>> happens. > >>> > >>> So you maybe able to > >>> 1) produce data > >>> 2) keep from overwriting it > >>> 3) enable the consumer to read data > >>> 4) have it send data (and I assume the callback happens here) > >>> 5) data is clobbered in the shared area, but we don't care since it's > >>> sent already > >>> 6) give the semaphore back allowing new data to be written > >>> 7) that data can't be clobbered by the callback (assuming) until after > >>> it's read and in the send process > >>> > >>> May solve the problem... > >>> > >>> > >>> > > >>> >Anyway, a little information that might be needed. socketCAN reads > data > >>> in > >>> >8 byte lengths for each frame..fastpackets are several frames in > length, > >>> >and with the only current one I'm tracking being 11 frames long. Or 88 > >>> >total bytes, not discounting the initial char from each frame which > is a > >>> >sequence number. If there is a way, and I'm sure there is, I am all > for > >>> >changing from an IPC model to a threaded model. But I still have some > >>> >doubts. Such as will it be fast enough to track multiple fastpackets a > >>> >second ? Past that how complex will it be ? > >>> > >>> Won't be all that complex, I think > >>> the processes are written as two parts > >>> one is a system call to set up a process > >>> the other is the process itself which looks like > >>> > >>> void processA(void* arguments if any) > >>> { > >>> // declarations and inits the first time through > >>> while (1) > >>> { > >>> basic process loop; > >>> } > >>> } > >>> > >>> not complicated at all, how to create the process ought to be well > >>> documented > >>> > >>> you just need to make sure that the two processes have access to > >>> shared memory > >>> > >>> assuming 1000 us available per process, a context switching time of 50 > >>> us (may be shorter, but it's a number) > >>> > >>> You have 950 us to send a complete message without it having a delay > >>> you have that same 950 us to detect and build a message. > >>> > >>> that gives you 500 message cycles/second > >>> > >>> taking twice as long gives you 250 message cycles/second and about > >>> 1950 us to compose and send a message, that's with a 2 ms clock tick. > >>> All that clock tick does is control task switching. The processor > >>> clock controls the speed of operations otherwise. > >>> > >>> > > >>> >I have given multiple approaches consideration, just having a hard > time > >>> >imaging how to work this out using a threading model. > >>> > >>> perhaps this might help > >>> > >>> Harvey > >>> > >>> (off to bed, have to be in training for 8 am classes in a week). > >>> > >>> -- > >>> For more options, visit http://beagleboard.org/discuss > >>> --- > >>> You received this message because you are subscribed to the Google > Groups > >>> "BeagleBoard" group. > >>> To unsubscribe from this group and stop receiving emails from it, send > an > >>> email to [email protected]. > >>> For more options, visit https://groups.google.com/d/optout. > >>> > >> > >> > > -- > For more options, visit http://beagleboard.org/discuss > --- > You received this message because you are subscribed to the Google Groups > "BeagleBoard" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > For more options, visit https://groups.google.com/d/optout. > -- For more options, visit http://beagleboard.org/discuss --- You received this message because you are subscribed to the Google Groups "BeagleBoard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
