Quote Originally Posted by http://marc.info/?l=linux-kernel&m=139524497906184&w=2
Dear all,

Cryogenic is a Linux kernel module that allows to reduce energy consumption
by means of enabling cooperative clustering of I/O operations among the various
applications that make use of the same hardware device. In order to achieve this
target, Cryogenic provides an API that enables applications to schedule I/O operations
on SCSI and network devices at times where the impact the operations have on
energy consumption is small.

Internally, Cryogenic defers (or anticipates) the execution of non-urgent tasks so that
they coincide with the performance of I/O operations requested by other urgent
applications. Therefore, background tasks operate when the device is already active
and they do not need to wake it up by themselves. Moreover, tasks using the same
device are ideally executed in a clustered way and, as a result, the idle periods become
longer.

The actual moment when an I/O operation is performed is determined by a tolerance
window set by the application developer. The window is defined by a minimum delay
and a maximum timeout, which ensures that the task will not indefinitely wait for other
I/O operations and starve as a result. The delay and the timeout must be properly
calculated and set by the programmer, since they determine the application behavior
and they are the key factor to trade-off between the responsiveness of the application
and the energy it consumes.

The architecture of Cryogenic defines an API composed of:

a) A character device under /dev/cryogenic/ for each targeted device
b) Redefinition of the following system calls: open, close, ioctl, select

The character devices, managed by the system calls, determine whether a task can
proceed with its operation. The call to ioctl is used to set the delay and the timeout for
each task, and select allows or forbids the execution of an I/O operation at a given time.

In order to see how to use the Cryogenic API, we present the following example:

1 main()
2 {
3 sock_fd = create_socket();
4 while() {
5 send(sock_fd);
6 sleep(period);
7 }
8 close(sock_fd)
9 }

This code is a simplified version of a UDP client that sends packets periodically.
In order to apply Cryogenic to this program, the following modifications are needed:

1) Open the character device corresponding to the active interface that is sending
the packets, which we need to know beforehand.
2) Within the main loop, and before the transmission, calculate the delay and the
timeout and pass it to Cryogenic by calling ioctl.
3) Call select before the transmission. The call to select will block until one of the
events that are meant to allow the resumption of the task happen: an I/O operation
requested by other applications or the expiration of the timeout that we set previously.
4) After the loop, close the file descriptor.

The resulting code looks like this:

1 main()
2 {
3 sock_fd = create_socket();
4 fd = open("/dev/cryogenic/wlan0");
5 while() {
6 times = calculate_delay_timeout(period);
7 ioctl(fd, times);
8 select(fd);
9 send(sock_fd);
10 }
11 close(fd);
12 close(sock_fd);
13 }

The call to sleep() has been removed since it is assumed now that the delay and the
timeout completely determine the transmission time. Nevertheless, this is just an
example and programmers may still want to keep it depending on the behavior
they want to achieve.

Cryogenic is the result of my Master's Thesis, completed at the Technical University
of Munich under the supervision of Christian Grothoff. You can find more information
about Cryogenic at https://gnunet.org/cryogenic

I would like to submit the module as a patch now, do you have any suggestions to
do this properly? Also, I would really appreciate any feedback about the code, which
you can find at the end of the e-mail. Thank you.

Best regards,
Alejandra Morales

let's see what the other developers' opinion about this is