This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

What s the right way to use NDK send recv function in multitask envirement?

Other Parts Discussed in Thread: AM3359

Hi All,

Here I met with a problem of ENOBUFS when sending . So I want to share my project structure to comfirm wether I use NDK in a right way.Thanks!

My software envirement:

XDCtools version: 3.25.0.48

SYSBIOS version: 6.35.1.29

NDK Core versison:2.22.3.20

am3359 ind sdk version : 1.1.0.3

Actrually what I want to achieve is two tasks call same send and receive function to send and receive raw ethernet packages. I achieve this by this way:

1. create one parent task ,in this task , I open one fd session and create two socket. socket_send for sending function and socket_rcv for receive function.

2.after creating the sockets.I create two child tasks.

3.In child tasks, fd session is opened in each task. Then these two tasks will call sendframe and receiveframe function when they need.

4.In sendframe function, at the begging it will call fdShare(socket_send), then call send function to send buffer out. fdClose will be called at the end of this function.

5.In receiveframe function, at the begging it will call fdShare(socket_rcv), then call recvnc function to receive from buffer in NDK. fdClose will be called at the end of this function.

Now when the application run for some time.I met with two problems:

1.The send funciton will meet with the ENOBUFS error and fail.

2.I dont know wether I need to free buffer after I call recvnc function. Cause when I try to recvncfree after recvnc, The NDK looks not able to receive at the next loop.

Code is like this:

void Task_Parent()

{

fdOpensession(TaskSelf());

socket_send = socket(AF_RAWETH, SOCK_RAWETH, rawether_type);

socket_rcv = socket(AF_RAWETH, SOCK_RAWETH, rawether_type);

... ...

Create child task 1;

Create child task 2:

}

void child task1()

{

fdOpensession(TaskSelf());

while(1)

{

    ... ...

    SendFrame();

    ..

    ..

    ReceiveFrame();

    ...

    . .

    }

}

void child task2()

{

fdOpensession(TaskSelf());

while(1)

{

    ... ...

    SendFrame();

    ..

    ..

    ReceiveFrame();

    ...

    . .

    }

}

void SendFrame()

{

    fdShare(socket_send);

    send(socket_send, buff, size, 0);

    ... ...

    fdClose(socket_send);

}

void ReceiveFrame()

{

    fdShare(socket_rcv);

    recvnc(socket_rcv, (void**)&(pkt_data), MSG_WAITALL, &hBuffer );

    ... ...

    fdClose(socket_rcv);

}

  • Hi Bin,

    I think the issue may be that you are creating two sockets, and sharing them, and simultaneously doing send and receive on the sockets from two different tasks.  For example, it looks like one task could call send(), and block, the other task could run, and call send() on the same socket while the other send() operation is in progress.  I’m not positive that this won’t work, but I’m pretty sure there could be issues doing this.  And it might be that the eventual ENOBUFS that you report on that other thread relates to this use model.

    The typical use model I’ve heard of is to create a “send” task and a separate “receive” task.  If you want to use the model you are using now, I think you may have to add some additional mutual exclusion methods, for example, to prevent one task from doing a send() on the socket when the other task has already called send() for the same socket.

    Regarding freeing the buffer after the recvnc() call.. this should work.  When you are calling recvncfree(), are you passing it the handle to the “phBuffer” returned by the recvnc() call?  Also, are you checking the return value of the recvnc() call?  Can you please post some actual code snippets of your calls to recvnc() and recvncfree()?

    Thanks,
    Scott

  • Hi Scott,

        Thank you very much! Problem solved.

        First ,I took your advice and add a binary semaphore to my send function to avoid calling the send socket function at the same time. Like this:

    {

    Semaphore_pend(socket_send_sem, BIOS_WAIT_FOREVER);

    fdShare(socket_send);

    /* Send down the packet */
    if((send(socket_send, buff, size, 0)) <= 0)
    {
    error = fdError();
    ConsoleUtilsPrintf("\nError sending the packet: %d\n", error);
    Semaphore_post(socket_send_sem);
    return -1;
    }

    fdClose(socket_send);

    Semaphore_post(socket_send_sem);

    }

        Second , in receive function I add the recvncfree function in it. I found out why last time I failed to call recvncfree, That is because some time recvnc call returns timeout and result is < 0, so that recvncfree will call failure. So I change the code to this:

    // Semaphore_pend(socket_rcv_sem, BIOS_WAIT_FOREVER);

    fdShare(socket_rcv);

    /* Retrieve the packets */
    bytesrx = (int)recvnc( socket_rcv, (void**)&(pkt_data), MSG_WAITALL, &hBuffer );

    ec_am335x_device->rx_buf = (uint8_t*)pkt_data;
    ecdev_receive(ec_am335x_device->ecdev,ec_am335x_device->rx_buf,bytesrx);

    if(bytesrx > 0)
    recvncfree(hBuffer);

    fdClose(socket_rcv);

    // Semaphore_post(socket_rcv_sem);

    Now every thing is OK.

    Thank you again!

  • Hi Bin,

    Great, thanks for reporting back, I’m very glad to hear this resolved the issues!

    Scott