io_uring: io_uring_wait_cqe_nr, io_uring_peek_batch_cqe - io-uring

I want to experiment io_uring on the github project:
https://github.com/alexhultman/io_uring_epoll_benchmark
referrence: https://unixism.net/loti/ref-liburing/completion.html
however I stumbled upon 2 functions:
unsigned io_uring_peek_batch_cqe(struct io_uring *ring, struct io_uring_cqe **cqes, unsigned count)
int io_uring_wait_cqe_nr(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr)
I understand that the first functions will fills in an array of I/O completions up to count to the cqes
and will return regardless of how many cqes completions
However the second functions only fills in one I/O completions to the cqes even I wait for wait_nr completions, why is this so, if it wait for specific number of cqes completions, why i didn't fill in the array of I/O like the first function did?
like example i create:
#define MAX_BATCH 2000
struct io_uring_cqe **cqes = malloc(sizeof(struct io_uring_cqe *) * MAX_BATCH);
if I run on the first function, i could access cqes[i] i = (0 to completions)
if I run on the second function, I can only access cqes[i] i = 0
I need to understand why the second function never update the array of cqes like the first function did

I've solved it, As the second function:
int io_uring_wait_cqe_nr(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, unsigned wait_nr)
will wait until for wait_nr completions cqe to complete before moving on, and it will return cqe I/O completions and update only the first array of cqes, which is cqes[0],
But for the first function:
unsigned io_uring_peek_batch_cqe(struct io_uring *ring, struct io_uring_cqe **cqes, unsigned count)
will return regardless whether or not theres a cqe, and will return the numbers of cqes and the array of cqes I/O
After checking the struct of cqes whether the asynchronous was done properly, mark it with the function:
void io_uring_cq_advance(struct io_uring *ring, struct io_uring_cqe *cqe, unsigned count) to free up the cqes entries so the next cqes will point to cqes[0]

Related

Can argv** be returned as a function return value

In C we should return pointer variable if define as 1- static stack 2- Heap-allocated 3-const address.
The question is:
Can argv** variable in main function be returned as a function return value without undefined behaviour?
I can't imagine a situation which requires to return argv** from a function, but you get it from main (int argc, char* argv[]) so yes. You can pass it as a parameter to a function and return it to another function. They're like const for you.
You can't return pointer to the data allocated temporarily for the function's own needs. int* F{ int A; return &A; } will not work. But you can set int* A=(int*)malloc(sizeof(int)); and return A;: it'll be your tiny wrapper around the malloc function. You can even receive int* A as a parameter and return A+1; the rule you mentioned in the beginning actually means "there are some restrictions of allocation methods if you're planning to use the pointer after the function exits". You can break the rule without returning the value (for example, you can store the poiner in a global variable and it'll become invalid when the function exits, like void F{ int A; GlobPtr=&A; } which will cause the same problems).
But your function does not allocate argv, it's allocated before your code starts. So you can even shift it by one value as you extract parameters one-by-one, the returned pointer *nextargv[] will also point to valid memory area.

Conversion with Pointsers in C

I need to implement but I am not sure how can I as I am completely new into this. A function called get_values that has the prototype:
void get_values(unsigned int value, unsigned int *p_lsb, unsigned int *p_msb,
unsigned int *p_combined)
The function computes the least significant byte and the most significant byte of the value
parameter. In addition, both values are combined. For this problem:
a. You may not use any loop constructs.
b. You may not use the multiplication operator (* or *=).
c. Your code must work for unsigned integers of any size (4 bytes, 8 bytes, etc.).
d. To combine the values, append the least significant byte to the most significant one.
e. Your implementation should be efficient.
The following driver (and associated output) provides an example of using the function you are
expected to write. Notice that in this example an unsigned int is 4 bytes, but your function
needs to work with an unsigned int of any size.
Driver
int main() {
unsigned int value = 0xabcdfaec, lsb, msb, combined;
get_values(value, &lsb, &msb, &combined);
printf("Value: %x, lsb: %x, msb: %x, combined: %x\n", value, lsb, msb, combined);
return 0;
}
Output
Value: abcdfaec, lsb: ec, msb: ab, combined: abec
I think you want to look into bitwise and and bit shifting operators. The last piece of the puzzle might be the sizeof() operator if the question is asking that the code should work with platforms with different sized int types.

With the Arduino Ethernet shield, what's the difference between `write()`, `print()`, and `printIn()`?

Using the Arduino Ethernet Server Library, what is the difference between:
server.write(data);,
server.print(data);, and
server.println(data);
I know that the printIn adds a new line, where print does not. I cannot find any examples for server.write();.
(Long answer, skip to TL;DR at the bottom if unwieldy)
Where print() and write() come from
To find out, we can look at the source. Server is an instance of the EthernetServer class defined in arduino/libraries/Ethernet/EthernetServer.h (selected lines only)
#include "Server.h"
class EthernetClient;
class EthernetServer :
public Server {
private:
public:
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);
using Print::write;
};
Ok, so it is a Server. Server is defined in /usr/share/arduino/hardware/arduino/cores/arduino/Server.h, and there is very little to it:
class Server : public Print {
public:
virtual void begin() =0;
};
This means that server is a subclass of Print so we can look for differences between write() and print() there.
print() and write() parameters
We see that this class (i.e. Print) defines a number of overloaded print() methods:
size_t print(const __FlashStringHelper *);
size_t print(const String &);
size_t print(const char[]);
size_t print(char);
size_t print(unsigned char, int = DEC);
size_t print(int, int = DEC);
size_t print(unsigned int, int = DEC);
size_t print(long, int = DEC);
size_t print(unsigned long, int = DEC);
size_t print(double, int = 2);
size_t print(const Printable&);
and three overloaded write() methods:
virtual size_t write(uint8_t) = 0;
size_t write(const char *str) { return write((const uint8_t *)str, strlen(str)); }
virtual size_t write(const uint8_t *buffer, size_t size);
As you can see the C-string write uses the block write (the third method), and in the default implementation, the block write uses a byte write (the first method), which is pure virtual method: virtual size_t write(uint8_t) = 0;. It must be overriden in every class that derives from Print. Additionally the block write() may be overriden as well in order to write multi-byte data more efficiently.
So, parameter-wise:
write(): on bytes (uint8_t), byte buffers, and char array pointers (= regular C strings)
print(): Arduino Strings, ints and longs (in whatever base), floats, and any class derived from Printable, in addition to chars and C strings.
As you can see, formally, there is little overlap between the parameters write() and print() takes. For instance only write() takes uint8_t, but only print() can take a char. The only area of overlap is the C-style strings: there is print(const char[]); and write(const char *str);. However, even in cases like char the print() function simply calls the write(uint8_t):
size_t Print::print(char c)
{
return write(c);
}
The same is true for print(char[])
write() in `EthernetServer
The EthernetServer class introduces a block write method
size_t EthernetServer::write(const uint8_t *buffer, size_t size)
and in the EthernetServer the write(uint8_t) simply thunks to the block write:
size_t EthernetServer::write(uint8_t b)
{
return write(&b, 1);
}
Since all the print() calls and non-uint8_t write() calls use either write(uint8_t) or write(uint8_t*, size_t), in the EthernetServer class every print/write call is made using the block write.
Performance and choosing between print() and write()
The thunking print() functions (such as print(char c)) will be most-likely be inlined by the gcc compiler, though if you are worried about this you can call write() instead of print().
One case where you might want to call write() instead of print() to save a couple of clock cycles is where you are holding a byte/uint8_t and you need to print that. Using print() your data will need to be converted to a 4-byte value (int) and then printed using more code. In this case write() will be a tiny bit faster.
On the other hand, code consistency is probably worth something too. From this perspective it might make sense to make all print() calls.
Most of the time, however, your types will dictate calling the print() function: write can only take three types of input.
TL;DR: The answer to your question then is that there isn't much difference between print() and write() except:
The write() methods (byte or block) are the methods that do the actual work of sending characters somewhere, in every case.
write() can take bytes (uint8_t), byte buffers, and char array pointers (= regular C strings) as parameters, whereas print() takes Arduino Strings, ints and longs (in whatever base), floats, and any class derived from Printable, in addition to chars and C strings. So we might say that write() is lower level than print(), given the fact that it only takes low-level types.
Most of the time your output types will dictate which one to use. To make the fastest code use write() for printing byte/uint8_t types, but print everywhere makes your code look a teensy bit better IMHO (mainly because it doesn't raise the print() versus write() questions).

Does CUDA support pointer-aliasing?

The reason why I ask this is because there is some strange bug in my code and I suspect it could be some aliasing problem:
__shared__ float x[32];
__shared__ unsigned int xsum[32];
int idx=threadIdx.x;
unsigned char * xchar=(unsigned char *)x;
//...do something
if (threadIdx.x<32)
{
xchar[4*idx]&=somestring[0];
xchar[4*idx+1]&=somestring[1];
xchar[4*idx+2]&=somestring[2];
xchar[4*idx+3]&=somestring[3];
xsum[idx]+=*((unsigned int *)(x+idx));//<-Looks like the compiler sometimes fail to recongize this as the aliasing of xchar;
};
The compiler only needs to honour aliasing between compatible types. Since char and float are not compatible, the compiler is free to assume the pointers never alias.
If you want to do bitwise operations on float, firstly convert (via __float_as_int()) to unsigned integer, then operate on that, and finally convert back to float (using __int_as_float()).
I think you have a race condition here. But I don't know what is somestring. If it is the same for all threads you can do like this:
__shared__ float x[32];
unsigned char * xchar=(unsigned char *)x;
//...do something
if(threadIdx.x<4) {
xchar[threadIdx.x]&=somestring[threadIdx.x];
}
__syncthreads();
unsigned int xsum+=*((unsigned int *)x);
It means that every thread shares the same array and therefore, xsum is the same between all threads. If you want that each thread has its own array, you have to allocate an array of 32*number_of_threads_in_block and use an offset.
PS: the code above works only in 1D block. In 2D or 3D you have to compute you own threadID and be sure that only 4 threads execute the code.

add value to struct to pointer segmentation error in C

people, i've an issue now..
#include <stdio.h>
#include <stdlib.h>
typedef struct a
{
int *aa;
int *bb;
struct b *wakata;
}a;
typedef struct b
{
int *you;
int *me;
}b;
int main()
{
a *aq;
aq = (a*)malloc(sizeof(a*));
*aq->wakata->you = 1;
*aq->wakata->me = 2;
free(aq);
return 0;
}
and compiled, then debugged :
gcc -o tes tes.c --debug
sapajabole#cintajangankaupergi:/tmp$ gdb -q ./tes
Reading symbols from /tmp/tes...done.
(gdb) r
Starting program: /tmp/tes
Program received signal SIGSEGV, Segmentation fault.
0x08048414 in main () at tes.c:22
22 *aq->wakata->you = 1;
well, the question is, how to set the value to variable inside struct 'b' through struct 'a' ?
anyone ?
The initial allocation of a is only allocating 4 bytes (in a 32-bit architecture). It should be:
aq = (a*)malloc(sizeof(a));
And wakata has not been initialized: Maybe this:
aq->wakata = (b*)malloc(sizeof(b));
And it will need a corresponding free as well prior to the free of aq.
free(aq->wakata);
And since you have pointers to the integers, those would also need to be allocated (you and me). But it is not clear if that is your goal. You probably should remove the * from the int declarations so that they are simply int members rather than the pointers to int.
Looks like you have a few mistakes here. See the code below.
In general a few things to keep in mind. You can't access memory before you malloc it. Also, there is a difference between memory and pointers e.g. int and int *
#include <stdio.h>
#include <stdlib.h>
typedef struct a
{
int aa;
int bb;
struct b *wakata;
}a;
typedef struct b
{
int you;
int me;
}b;
int main()
{
a * aq = malloc(sizeof(a));
aq->wakata = malloc(sizeof(b))
aq->wakata->you = 1;
aq->wakata->me = 2;
free(aq->wakata)
free(aq);
return 0;
}
wakata isn't pointing to any valid memory. You have to malloc memory for it, and then also for wakata->you and wakata->me
Pointers do not contain data. They point at data. That is why they are called pointers.
When you malloc enough space to store an a instance named aq, you allocate space for the pointers contained in that structure. You do not cause them to point at anything, nor do you allocate space to contain the things that they would point at.
You're not allocating space for b in struct a. You have defined 'a' as holding pointers, not structs. Also, I think malloc(sizeof(a*)) should be malloc(sizeof(a))
aq = (a*)malloc(sizeof(a)); // You should probably use calloc here
aq->wakata = (b*)malloc(sizeof(b));
you and me don't seem to need to be pointers, just normal ints
You have some problems with your code.
When you allocate memory for the struct a, you should do
aq = (a*)malloc(sizeof(a));
You now allocated memory for the struct a, but not for the struct b pointed by the wakata member, so you need to do
aq->wakata = (b*)malloc(sizeof(b));
Finally, in the struct b there should not be int* members, but int members. This way, you'll be able to correctly assign a value to them.
Remember that you should check for the correct allocation of memory by checking if the malloc return value is not NULL.

Resources