On Tue, 25 Aug 2015 15:11:30 -0700, you wrote:

If it works, then you have the solution.  

Good.

Harvey

>Anyway, I refactored the code, and wound up removing *a lot* of dead weight
>code after the refactor. Went from using a union + struct data type to just
>using a struct.
>
>Then changed the way my old binary locking mechanism worked. From 0->
>unlocked / 1->locked to 0-> IPC server has access / 1-> IPC client has
>access. Which works out exactly how I'd prefer it to. e.g. procedural /
>deterministic, and one process will wait on the other indefinitely. Which
>is a deadlock, but only one process running means the data is either old,
>or not needed anyway. But like so . .
>
>IPC server:
>
>while(1){
>        frame = ReadFrame(sock);
>        if(frame.can_dlc == FRAME_DLC)
>            stats = ProcessFastpacket(frame);
>
>        if(stats != NULL){
>
>*while(smd->file_lock != 0)                usleep(1000);*
>
>            WriteToShm(smd, stats);
>            *smd->file_lock = 1;*
>
>            stats = NULL;
>            printf("%s", ReadFromShm(smd));
>        }
>    }
>
>IPC client:
>
>while(1){
>                mg_poll_server(server, 100);
>
>
>*while(smd->file_lock != 1)                        usleep(1000);*
>
>                push_message(server, smd->data);
>                *smd->file_lock = 0;*
>        }
>
>I do not think it will get any faster, or simpler than this.
>
>On Tue, Aug 25, 2015 at 11:47 AM, William Hermans <yyrk...@gmail.com> wrote:
>
>> Harvey,
>>
>> Yeah, wow semaphores will *not* work! heh.
>>
>> So using sem_wait() / sem_post() introduces incredibly long stalls. Even
>> when using a single process. The webserver which uses libmongoose wont even
>> function. Hell I put a printf() in the front of my control loop, and that
>> doesn't even work :/
>>
>> Going to do some more digging, and see if I can somehow make this work.
>>
>> On Mon, Aug 24, 2015 at 6:32 PM, Harvey White <ma...@dragonworks.info>
>> wrote:
>>
>>> On Mon, 24 Aug 2015 18:19:14 -0700, you wrote:
>>>
>>> >>
>>> >> *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.
>>>
>>> It's more of a general operating system issue, and that is fundamental
>>> knowledge.  Personally, I don't see a problem, but the list moderators
>>> haven't seemed to have a problem either, so that's ok.
>>>
>>> >
>>> >*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.
>>>
>>> True, except it *is* to get the beaglebone working, and *is* an issue
>>> that can bite people writing somewhat more complicated projects.
>>>
>>> I'd hope that it will help others, and for that matter, if someone
>>> disagrees with what I've said, I'd welcome the discussion.
>>>
>>> Hopefully, the concepts will help with the more complicated projects
>>> using any sort of beagle....
>>>
>>> Harvey
>>>
>>> >
>>> >On Mon, Aug 24, 2015 at 6:00 PM, Harvey White <ma...@dragonworks.info>
>>> >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 <yyrk...@gmail.com>
>>> >> wrote:
>>> >> >
>>> >> >> OK have a good one, thanks for the discussion.
>>> >> >>
>>> >> >> On Sun, Aug 23, 2015 at 9:11 PM, Harvey White <
>>> ma...@dragonworks.info>
>>> >> >> 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 beagleboard+unsubscr...@googlegroups.com.
>>> >> >>> 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 beagleboard+unsubscr...@googlegroups.com.
>>> >> 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 beagleboard+unsubscr...@googlegroups.com.
>>> 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 beagleboard+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to