structkfifo { unsignedchar *buffer; /* the buffer holding the data */ unsignedint size; /* the size of the allocated buffer */ unsignedint in; /* data is added at offset (in % size) */ unsignedint out; /* data is extracted from off. (out % size) */ spinlock_t *lock; /* protects concurrent modifications */ };
/* * round up to the next power of 2, since our 'let the indices * wrap' tachnique works only in this case. */ if (size & (size - 1)) { //判断size是否是二的幂 BUG_ON(size > 0x80000000); size = roundup_pow_of_two(size); }
buffer = kmalloc(size, gfp_mask); if (!buffer) return ERR_PTR(-ENOMEM);
len = min(len, fifo->size - fifo->in + fifo->out);//需要长度和空闲长度的最小值
/* first put the data starting from fifo->in to buffer end */ l = min(len, fifo->size - (fifo->in & (fifo->size - 1)));//需要长度和末端长度的最小值 memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l);//一部分放到末端
/* then put the rest (if any) at the beginning of the buffer */ memcpy(fifo->buffer, buffer + l, len - l);//一部分放到起端
/* first get the data from fifo->out until the end of the buffer */ l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l);//to,from
/* then get the rest (if any) from the beginning of the buffer */ memcpy(buffer + l, fifo->buffer, len - l);