Friday, November 21, 2008

Jari OS: device drivers development wellness

I have a lot of time spent with drivers development in different OSes/kernels. Generally it was microkernel or hybrid kernels and I cannot told that this process takes me into pleasure.
Jari OS on other side is a new microkernel OS that can takes in advance all my skills with system design.
Actually every Jari driver is a microkernel service working in userspace like a trusted task. All IO mechanics has a protocol and every time you need to support it with all changes. It's a bad, but for this case I've designed a generic device server layer that will hide all semantics within several library functions.
All of this located in system libraries - in LibOS part.
Include and you will have server implemented. Really is a generic layer - on top of this I will design and implement other layers - for console drivers, input drivers, block drivers and so on.
Like example of this I will show a code snippet of the generic VGA console driver uses this generic layer:


#include <sys/types.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <wchar.h>
#include <errno.h>
#include <time.h>
#include <datalib/usrtc.h>
#include <ns/ns.h>
#include <scheduler.h>
#include <proto/rpc.h>
#include <devio/devio.h>
#include <devio/server.h>
#include <termio/termio.h>

#include <termio/term.h>

#include "vga.h"
#include "hwops.h"

#define DRVNAME "vgacons.d"
#define DEVNAME "/console"

static size_t __vga_write(void *buf,uni_rpc_t rpc,size_t size,size_t offset);
static size_t __vga_read(void *buf,uni_rpc_t rpc,size_t size,size_t offset);
static int __vga_ioctl(void *buf,uni_rpc_t *rpc,size_t size);

struct device_ops dev_op = {
__vga_write,
__vga_read,
NULL,
__vga_ioctl,
__vga_write,
__vga_read,
NULL,
NULL,
};

int main(int argc,char **argv)
{
device_server_t *sys;
int r=0;
void *iobuf=mmap(NULL,4096,MMAP_RW|MMAP_PHYS,NOFD,(void*)VGA_TM_BASE);
char buff[256];

task_scheduler_control(getpid(),SYS_SCHED_CTL_SET_PRIORITY,30);

vga_init(iobuf);

vga_print("[vgacons] i've started\n");

sys=malloc(sizeof(*sys));
if(!sys)
abort();

r=init_device_server(sys,DIRECTIO_READ | DIRECTIO_WRITE | HW_READ | HW_WRITE,
2048,4096,512,1,DRVNAME,DEVNAME,&dev_op,4);

sprintf(buff,"sys->allowed = %p\n",sys->allowed);
vga_print(buff);

if(r!=0) {
sprintf(buff,"r=%d\n",r);
vga_print(buff);
abort();
}

vga_print("[vgacons] device server run\n");

device_server_start(sys);

vga_print("[vgacons] :((\n");

return 0;
}

static size_t __vga_write(void *buf,uni_rpc_t rpc,size_t size,size_t offset)
{
char *msg=buf;
size_t rsize=size;

if(size<=sizeof(rpc)) {
return -EINVAL;
}
msg+=sizeof(rpc);
size-=sizeof(rpc);

switch(rpc.arg3) {
case PHYT_WRITE:
uni_print((cschar_t*)msg,size);
break;
case PHYT_WRITEPOS:
uni_printxy((cschar_t*)msg,size,rpc.arg4,rpc.arg5);
break;
case PHYT_SCROLL:
if(rpc.arg4==SCROLL_UP) {
uni_scrollup(rpc.arg5);
uni_printxy((cschar_t*)msg,size,0,0);
} else if(rpc.arg3==SCROLL_DOWN) {
uni_scrolldown(rpc.arg5);
uni_printxy((cschar_t*)msg,size,0,uni_height()-rpc.arg5);
} else
return -EINVAL;
break;
default:
return -EINVAL;
break;
}

return rsize;
}

void ascii_puts(const char *msg)
{
return;
}

static size_t __vga_read(void *buf,uni_rpc_t rpc,size_t size,size_t offset)
{

vga_print("ridden\n");

return 0;
}

static int __vga_ioctl(void *buf,uni_rpc_t *rpc,size_t size)
{
uni_rpc_t rrpc;

if(size<sizeof(rrpc))
return EINVAL;

memcpy(&rrpc,buf,sizeof(rrpc));
switch(rrpc.arg3) {
case PHYT_DISABLEAUTOSCROLL:
uni_scrolldisable();
rpc->rpc_call=0;
break;
case PHYT_ENABLESCROLL:
uni_scrollenable();
rpc->rpc_call=0;
break;
case PHYT_GETSIZE:
rpc->rpc_call=0;
rpc->arg0=uni_width();
rpc->arg1=uni_height();
break;
case PHYT_CLEAR:
uni_clear();
break;
default:
return EINVAL;
break;
}

return 0;
}

Wednesday, November 12, 2008

Jari Operating System: LibAlloc updates

Some of today's deal within Jari OS project was dlmalloc (Douglas Lee memory allocator) porting.
So, it's done and now I've rejected using of ugly smalloc (simple memory allocator).
Dlmalloc is a great thing - it can be ported anywhere, for example - Jari OS doesn't have sbrk() function, and will not have this oldish shit, otherwise - all is done via mmap() and dlmalloc allow to use it without sbrk().
Porting to the Jari OS mmap() semantics taken few minutes only.
Like usually you can look out source code - git clone git://rep.jarios.org/syslibs.git - LibAlloc/lib/dlmalloc.c

thanks.

Tuesday, October 28, 2008

Jari Operating System: small steps

I want to make an announcement of development steps.
First of all is a really progress on microkernel (http://mstring.jarios.org) - there are many features implemented:
- memory management (O(1) allocator)
- interrupts handling for uspace
- memory i/o for uspace
- ioports for uspace
- realtime scheduler
- running static ELF binaries that loaded from GNU grub
- Fast IPC (sync ports)
Actually muistring allow to write userspace drivers and subsystems now, but some things not done yet.
Uspace (Jari) is developing now and some things works:
- nameserver
- terminals server
- text VGA driver
- keyboard driver
- syslibs (libos, libc, liballoc)
Some later I will post link to showcase.
More information here - http://jarios.org

Tuesday, September 16, 2008

Jari Operating System: reburned

I don't have a time to write more.
This is just a copy-paste from news feed:
After Jari was frozen for a many years, now Jari is wake up and preparing to work, for a hard work.
Jari Operating System will be a not microkernel/hybrid based system, otherwise it will use an exokernel, that developing separately. It's mean that Jari Operating System is a set of user-space drivers, network libs, libOS, libc and so on. It's a top level of a exokernel.
While exokernel under extreme development stage and not all syscalls are well defined, this project will wait for this and will temproary suspended (for several weeks or one month, it cannot be determined now). After those userspace wrappers will be implemented and user-space development begins.
After core libs are well tested and exokernel will be done this all will be ported to it.
In case of exokernel Jari changing default architecture to amd64 (not x86_64, just amd64 in case of its specific hardware features), but Jari portable, and all depends on exokernel ports.
So, I will present an exokernel -> http://mstring.jarios.org , it's called MuiString (greek mui at the begging) that shows it's small size, and string just a mode for kernel flexibility and atomicity (you know about string theory).
Generally it mean that Jari found a kernel to base on, ... it was a
long search ...

Also I want to introduce a new Jari OS homesite - http://jarios.org, you can find a lot of
information there.

Thanks.

ReadLeaf: updates

I want to make announcment.
ReadLeaf 0.2alpha is out with many new features.
You can look out for more info here - http://www.readleaf.org

Tuesday, August 05, 2008

Xmonad: optimizing working space

Some later I wrote about Gnome and how to change default metacity wm (that very good and cannot be in use if you want to make your works faster) with windowmaker.
I've decide reject Gnome and use pure wm without desktop environment, but also I've decided to try tiling wm written on Haskell - XMonad.
It's really usable, for indication I'm using a dzen2 and some set of handmade icons.
Here my ~/.xmonad/xmonad.hs

import XMonad hiding ((|||))
import XMonad.Operations
import System.Exit
import Graphics.X11
import System.IO

import qualified XMonad.StackSet as W
import qualified Data.Map as M

import XMonad.Hooks.DynamicLog
import XMonad.Hooks.UrgencyHook
import XMonad.Layout.Tabbed
import XMonad.Layout.NoBorders
import XMonad.Hooks.ManageDocks
import XMonad.Layout.Grid
import XMonad.Layout.ToggleLayouts


import XMonad.Layout.LayoutCombinators ((|||))
import XMonad.Util.Run (spawnPipe)


------------------------------------------------------------------------
-- Common variables
--
myTerminal = "urxvt"
myBorderWidth = 1
myModMask = mod4Mask
myNumlockMask = mod2Mask
myWorkspaces = ["Shells","Emacs","WWW","IM", "Docs", "Media" ] ++ map show [6..9]
myNormalBorderColor = "#3e7464"
myFocusedBorderColor = "#0b610b"
myNormalBg = "#0b0b0b"
myNormalFg = "#385c64"
myFocusedBg = "#598867"
myFocusedFg = "#760202"
myFont = "-misc-*-*-*-*-*-10-*-*-*-*-*-*-*"
myBitmapsDir = "/home/tirra/Icons/"

myDefaultGaps :: [(Int,Int,Int,Int)]
myDefaultGaps = [(14,0,0,0)] -- 15 for default dzen

menuCmd = "dmenu -fn '" ++ myFont ++ "' -nb '" ++ myNormalBg ++ "' -nf '" ++ myNormalFg ++ "' -sb '" ++ myFocusedBg ++ "' -sf '" ++ myFocusedFg ++ "'"
dzen2 = "dzen2 -p -h 14 -ta l -bg '" ++ myNormalBg ++ "' -fg '" ++ myNormalFg ++ "' -w 600 -sa c -fn '" ++ myFont ++ "'"

------------------------------------------------------------------------
-- Key bindings. Add, modify or remove key bindings here.
--
myKeys conf@(XConfig {XMonad.modMask = modMask}) = M.fromList $
[ ((modMask, xK_r ), spawn ("exec `dmenu_path | " ++ menuCmd ++ "`"))
, ((modMask, xK_q ), kill)
, ((modMask .|. shiftMask, xK_a ), spawn "urxvt")
, ((modMask .|. shiftMask, xK_e ), spawn "emacs")
, ((modMask .|. shiftMask, xK_m ), spawn "urxvt -e mutt")
, ((modMask, xK_space ), sendMessage NextLayout)
, ((modMask .|. shiftMask, xK_space ), setLayout $ XMonad.layoutHook conf)
, ((modMask, xK_n ), refresh)
, ((modMask, xK_Tab ), windows W.focusDown)
, ((modMask, xK_j ), windows W.focusDown)
, ((modMask, xK_k ), windows W.focusUp )
, ((modMask, xK_m ), windows W.focusMaster )
, ((modMask, xK_Return), windows W.swapMaster)
, ((modMask .|. shiftMask, xK_j ), windows W.swapDown )
, ((modMask .|. shiftMask, xK_k ), windows W.swapUp )
, ((modMask, xK_h ), sendMessage Shrink)
, ((modMask, xK_l ), sendMessage Expand)
, ((modMask, xK_t ), withFocused $ windows . W.sink)
, ((modMask , xK_comma ), sendMessage (IncMasterN 1))
, ((modMask , xK_period), sendMessage (IncMasterN (-1)))
, ((modMask .|. shiftMask, xK_q ), io (exitWith ExitSuccess))
, ((modMask , xK_f), (sendMessage (Toggle "Full")) >> sendMessage (Toggle "Grid"))
, ((modMask .|. shiftMask, xK_r ),
broadcastMessage ReleaseResources >> restart "xmonad" True)
]

++

--
-- mod-[1..9], Switch to workspace N
-- mod-shift-[1..9], Move client to workspace N
--
[((m .|. modMask, k), windows $ f i)
| (i, k) <- zip (XMonad.workspaces conf) [xK_1 .. xK_9]
, (f, m) <- [(W.greedyView, 0), (W.shift, shiftMask)]]


------------------------------------------------------------------------
-- Mouse bindings: default actions bound to mouse events
--
myMouseBindings (XConfig {XMonad.modMask = modMask}) = M.fromList $

-- mod-button1, Set the window to floating mode and move by dragging
[ ((modMask, button1), (\w -> focus w >> mouseMoveWindow w))

-- mod-button2, Raise the window to the top of the stack
, ((modMask, button2), (\w -> focus w >> windows W.swapMaster))

-- mod-button3, Set the window to floating mode and resize by dragging
, ((modMask, button3), (\w -> focus w >> mouseResizeWindow w))

-- you may also bind events to the mouse scroll wheel (button4 and button5)
]

------------------------------------------------------------------------
-- Layouts:

-- You can specify and transform your layouts by modifying these values.
-- If you change layout bindings be sure to use 'mod-shift-space' after
-- restarting (with 'mod-q') to reset your layout state to the new
-- defaults, as xmonad preserves your old layout settings by default.
--
-- The available layouts. Note that each layout is separated by |||,
-- which denotes layout choice.
--


myTabConfig = defaultTheme {
activeColor = "#6666cc"
, activeBorderColor = "#000000"
, inactiveColor = "#666666"
, inactiveBorderColor = "#000000"
, decoHeight = 10
}


------------------------------------------------------------------------
-- Window rules:

myManageHook = composeAll [ className =? "Firefox-bin" --> doF(W.shift "WWW")
, className =? "Iceweasel" --> doF(W.shift "WWW")
, className =? "Gajim.py" --> doF(W.shift "IM")
, className =? "Evince" --> doF(W.shift "Docs")
, className =? "Emacs" --> doF(W.shift "Emacs")
, title =? "mutt" --> doF(W.shift "WWW")
, className =? "URxvt" --> doF(W.shift "Shell")
, className =? "Stardict" --> doF(W.shift "Docs")
]



------------------------------------------------------------------------
-- dzen2 configuration
--

myPP h = defaultPP {
ppOutput = hPutStrLn h
, ppCurrent = dzenColor myFocusedFg myFocusedBg . pad
, ppVisible = dzenColor myNormalFg myNormalBg . pad
, ppTitle = dzenColor "#117418" "" . wrap "{ " " }"
, ppHiddenNoWindows = const ""
, ppWsSep = " ^fg(#113d41)^r(1x12)^fg() "
, ppSep = " ^fg(#113d41)^r(2x2)^fg() " -- "|"
-- , ppLayout = dzenColor "#946144" "" .
-- (\x -> case x of
-- "Tall" -> "^i(/home/dk/.icons/dzen2/tall.xbm)"
-- "Mirror Tall" -> "^i(/home/dk/.icons/dzen2/mtall.xbm)"
-- "Full" -> "^i(/home/dk/.icons/dzen2/full.xbm)"
-- )
}

myUrgencyHook = withUrgencyHook dzenUrgencyHook
{ args = ["-bg", myNormalBg, "-fg", "#117418"] }


------------------------------------------------------------------------
-- Run xmonad with the settings you specify. No need to modify this.
--
main = do din <- spawnPipe dzen2
xmonad $ myUrgencyHook $
defaultConfig {
-- simple stuff
terminal = myTerminal,
-- focusFollowsMouse = myFocusFollowsMouse,
borderWidth = myBorderWidth,
modMask = myModMask,
numlockMask = myNumlockMask,
workspaces = myWorkspaces,
normalBorderColor = myNormalBorderColor,
focusedBorderColor = myFocusedBorderColor,
defaultGaps = myDefaultGaps,

-- key bindings
keys = myKeys,
mouseBindings = myMouseBindings,

-- hooks, layouts
layoutHook = toggleLayouts (noBorders Full) $
smartBorders $ tiled ||| Mirror tiled ||| Full ||| Grid ||| tabbed shrinkText myTabConfig,
manageHook = (manageHook defaultConfig <+> myManageHook) <+> manageDocks,
logHook = dynamicLogWithPP $ myPP din
}
where
tiled = Tall 1 0.03 0.68

There are many tuning for yourself can be made. For dzen2 I wrote two files - one of this just runs it, other is a daemon that takes information and provide it to dzen2 panel.
Main file - ~/.xmonad/panel.sh

#!/bin/bash

export LANG=en_US.UTF-8
FONT='-misc-*-*-*-*-*-10-*-*-*-*-*-*-*'
DZEN="dzen2 -p -h 14 -fn $FONT"
BG="#0b0b0b"
FG="#385c64"
MONITOR=/home/tirra/.xmonad/monitor.pl

SW=1280
Y=0
X=600
$MONITOR | $DZEN -e '' -x $X -y $Y -ta r -bg $BG -w $(($SW-$X)) -fg $FG -sa c

And ~/.xmonad/monitor.pl where you need to made some modifications:

#!/usr/bin/perl

use strict;

###
# Configurable constants
#
## Xbm icons directory
use constant XBM_IDIR => '/home/tirra/Icons';
## Colors, separators and other stuff of this kind
use constant FG_COLOR => '#385c64';
use constant BG_COLOR => '#010101';
use constant TITLE_COLOR => '#946144';
use constant ELEM_COLOR => '#5c0000';
use constant ICON_COLOR => '#00baff';
use constant VSEP => '^fg(#113d41)^r(1x12)^fg()';
use constant ISEP => '^p(6)^fg(#113d41)^r(2x2)^fg()^p(6)';
## IDLE time
use constant IDLE => 1;
## Constants for CPU load measurment
use constant FSTAT => '/proc/stat';
use constant NCPUS => 2; # number of CPUs in system
## Battery constants
use constant BAT_STATUS => '/sys/class/power_supply/BAT1/status';
use constant BAT_CHARGE_NOW => '/sys/class/power_supply/BAT1/charge_now';
use constant BAT_CHARGE_FULL => '/sys/class/power_supply/BAT1/charge_full';
use constant BAT_FULL_ICON => XBM_IDIR . '/b_full.xbm';
use constant BAT_CRITICAL_ICON => XBM_IDIR . '/b_critical.xbm';
use constant BAT_EMPTY_ICON => XBM_IDIR . '/b_empty.xbm';
use constant BAT_25_ICON => XBM_IDIR . '/b_25.xbm';
use constant BAT_50_ICON => XBM_IDIR . '/b_50.xbm';
use constant BAT_75_ICON => XBM_IDIR . '/b_75.xbm';
use constant BAT_CHRG_ICON => XBM_IDIR . '/ac_01.xbm';
## Constants for memory monitoring
use constant MEMINFO => '/proc/meminfo';
## Net interface constants
use constant ROUTE => '/sbin/route';
use constant NETPATH => '/sys/class/net/';
use constant NET_UP_ICON => XBM_IDIR . '/arr_up.xbm';
use constant NET_DOWN_ICON => XBM_IDIR . '/arr_down.xbm';
use constant NET_PPPDOWN_ICON => XBM_IDIR . '/ppp_down.xbm';
use constant NET_PPPUP_ICON => XBM_IDIR . '/ppp_up.xbm';
use constant NET_ETHDOWN_ICON => XBM_IDIR . '/eth_down.xbm';
use constant NET_ETHUP_ICON => XBM_IDIR . '/eth_up.xbm';
use constant NET_WLANDOWN_ICON => XBM_IDIR . '/wlan_down.xbm';
use constant NET_WLANUP_ICON => XBM_IDIR . '/wlan_up.xbm';
## Jabber constatns
use constant JNAME => 'IM';
use constant ACOLOR => '#117418';
## Weather constants
use constant WTITLE => 'Out';
use constant WID => 'yourweatheridhere';
use constant WUPD_INT => 30 * 60;

######
# Cpu load measurment in percents.
#
my @cpus = undef;
my $stat_fh = undef;

sub init_cpus()
{
for (my $i = 0; $i < NCPUS; $i++) {
$cpus[$i] = { 'old_idle' => 1, 'old_load' => 1 };
}

open($stat_fh, '<', FSTAT) or die "Can't open file " . FSTAT . " for reading $!";
}

sub get_cpus_load_perc()
{
my @cpus_load = undef;

for (my $i = 0; $i < NCPUS; $i++) {
while (<$stat_fh>) {
next if (!/^cpu$i.+/);
# /proc/stat should contain all data about CPU in the following
# format(all data about particular CPU is written in one line):
# cpu:
#
my @load = split /\s/;
my $idle_time = $load[4];
my $load_time = $load[1] + $load[2] + $load[3] + $load[5] + $load[6] + $load[7];
$cpus_load[$i] = int(($load_time - $cpus[$i]->{'old_load'}) /
($idle_time + $load_time - $cpus[$i]->{'old_idle'} -
$cpus[$i]->{'old_load'}) * 100);
$cpus[$i]->{'old_idle'} = $idle_time;
$cpus[$i]->{'old_load'} = $load_time;
last if ($i++ == NCPUS);
}
}

die "Can't make seek on " . FSTAT . "$!" if (seek($stat_fh, 0, 0) < 0);
return @cpus_load;
}

sub show_cpu_info()
{
my @cpu_info = get_cpus_load_perc();
my $tmp = "";

print "^fg(" . TITLE_COLOR . ")CPU:^fg()^p(6)";
for (my $i = 0; $i < NCPUS; $i++) {
$tmp .= "$cpu_info[$i]%";
$tmp .= " " . VSEP . " " if ($i + 1 != NCPUS);
}

print $tmp;
}

######
# Laptop's battery state
#

# returns an array of two elements
# where first element is a current power of battery in percens
# and the second one is a boolean value showing if the battry is
# charged or not.
sub get_battery_state()
{
my @bat_state = undef;
my $bat_max = 0;
my $bat_cur = 0;

open(BFC, '<', BAT_CHARGE_FULL) or die "Can't open file " . BAT_CHARGE_FULL . "for reading $!";
while () {
$bat_max = $_;
last;
}

close(BFC);

open(BFC, '<', BAT_CHARGE_NOW) or die "Can't open file " . BAT_CHARGE_NOW . "for reading $!";
while () {
$bat_cur = $_;
last;
}

close(BFC);
$bat_state[0] = int($bat_cur / $bat_max * 100);

open(BFC, '<', BAT_STATUS) or die "Can't open file " . BAT_STATUS . "for reading $!";
while () {
$bat_state[1] = $_;
last;
}

close(BFC);


return @bat_state;
}

sub show_battery_info()
{
my @binfo = get_battery_state();
my $icon = BAT_EMPTY_ICON;

if($binfo[0] <= 1) {
$icon = BAT_EMPTY_ICON;
}
elsif($binfo[0] <= 10) {
$icon = BAT_CRITICAL_ICON;
}
elsif($binfo[0] <= 25) {
$icon = BAT_25_ICON;
}
elsif($binfo[0] <=50) {
$icon = BAT_50_ICON;
}
elsif($binfo[0] < 99) {
$icon = BAT_75_ICON;
}
elsif($binfo[0] >= 99) {
$icon = BAT_FULL_ICON;
}


print "^fg(" . ICON_COLOR . ")^i($icon)^fg()";
}

######
# Memory usage monitor.
#

sub get_meminfo()
{
my ($mtotal, $mactive, $stotal, $sfree, $cached) = (0, 0, 0, 0, 0);
my %minfo = undef;

open(MIF, '<', MEMINFO) or die "Can't open file " . MEMINFO . " for reading $!";
while () {
if (/^MemTotal:\s+(\d+).*$/) {
$mtotal = $1;
}
elsif (/^Active:\s+(\d+).*$/) {
$mactive = $1;
}
elsif (/^SwapTotal:\s+(\d+).*$/) {
$stotal = $1;
}
elsif (/^SwapFree:\s+(\d+).*$/) {
$sfree = $1;
}
elsif (/^Buffers:\s+(\d+).*$/) {
$cached = $1;
}
}

close(MIF);
$minfo{'in_use'} = int($mactive / $mtotal * 100);
$minfo{'cached'} = int($cached / $mtotal * 100);
$minfo{'swap'} = int(($stotal - $sfree) / $stotal * 100);

return %minfo;
}

sub show_mem_info()
{
my %minfo = get_meminfo();

print "^fg(" . ICON_COLOR . ")MEM:^fg() ";
print $minfo{'in_use'} . "% ";
}

######
# Network monitor.
#

my @old_netstat = (0, 0);
my $network_avail = 0;

# Get current speed of the interface and
# quantoty of received and transmitted trough it bytes
sub get_net_info(@_)
{
my $ifname = shift;
my $file = NETPATH . "/$ifname/statistics/rx_bytes";
my @stat = undef;

open(RXF, '<', $file) or die "Can't open file $file for reading $!";
my $rx_bytes = ;
close(RXF);

$file = NETPATH . "/$ifname/statistics/tx_bytes";
open(TXF, '<', $file) or die "Can't open file $file for reading $!";
my $tx_bytes = ;
close(TXF);

$stat[0] = int(($rx_bytes - $old_netstat[0]) / 1024);
$stat[1] = int(($tx_bytes - $old_netstat[1]) / 1024);
$old_netstat[0] = $rx_bytes;
$old_netstat[1] = $tx_bytes;

return @stat;
}

sub show_net_info()
{
my $cmd = ROUTE . " -n | grep -e '^0.0.0.0' | awk '{print \$8}'";
my $iface = `$cmd`;
my $iconppp = NET_PPPDOWN_ICON;
my $iconwlan = NET_WLANDOWN_ICON;
my $iconeth = NET_ETHDOWN_ICON;

chomp($iface);

if ($iface eq 'ppp0') {
$iconppp = NET_PPPUP_ICON;
}

if ($iface eq 'wlan00') {
$iconwlan = NET_WLANUP_ICON;
}

if ($iface eq 'eth0') {
$iconeth = NET_ETHUP_ICON;
}


if ($iface eq '') {
$network_avail = 0;
@old_netstat = (0, 0);
print " ^fg(" . ICON_COLOR . ")^i($iconeth)^fg()";
print " ^fg(" . ICON_COLOR . ")^i($iconwlan)^fg()";
print " ^fg(" . ICON_COLOR . ")^i($iconppp)^fg()";
return;
}

my @stat = get_net_info($iface);

$network_avail = 1;
print " ^fg(" . ICON_COLOR . ")^i($iconeth)^fg()";
print " ^fg(" . ICON_COLOR . ")^i($iconwlan)^fg()";
print " ^fg(" . ICON_COLOR . ")^i($iconppp)^fg()";

# print "^fg(" . TITLE_COLOR . ")$iface:^fg()^p(6)$stat[0]";
# print "^fg(" . ELEM_COLOR . ")^i(" . NET_DOWN_ICON . ")^fg() ";
# print VSEP . " $stat[1]^fg(" . ELEM_COLOR . ")^i(" . NET_UP_ICON . ")^fg()";
}

####
# Jabber monitor.
#

sub get_nmessages()
{
my @procs = split('\n', `ps aux | grep gajim`);
my $found = 0;

foreach (@procs) {
next if (/.*?\s+e?grep.*$/);
$found = 1;
last;
}
if ($found) {
my $num = `gajim-remote get_unread_msgs_number`;
chomp($num);
return $num;
}

return '-';
}

sub show_jabberinfo()
{
my $nmsg = get_nmessages();
print "^fg(" . ICON_COLOR . ")" . JNAME . ":^fg()^p(6)";
if (($nmsg ne '-') && ($nmsg > 0)) {
print "^fg(" . ACOLOR . ")$nmsg^fg()";
}
else {
print "$nmsg";
}
}

###
# Weather monitor
#

my $last_wupd_time = 0;
my $last_temp = undef;

sub get_temperature()
{
my $cmd = 'weather -i ' . WID;
my @data = split(/\n/, `$cmd`);
my $temp = undef;

foreach (@data) {
next until(/\s+Temperature:.+?\((-?\d+)\s+C\).*$/);
$temp = "$1";
$temp = "+$temp" if ($1 > 0);
$temp .= "C";
last;
}

return $temp;
}

sub show_temperature()
{
my $time = time();
my $temp = undef;

if (!$network_avail) {
$temp = '-';
}
elsif (($time - $last_wupd_time) >= WUPD_INT) {
$temp = get_temperature();
$last_temp = $temp;
$last_wupd_time = $time;
}
else {
$temp = $last_temp;
}

print "^fg(" . ICON_COLOR . ")" . WTITLE . ":^fg()^p(6)$temp";
}

####
# Time
#

sub show_time()
{
my $time = `date +'%H:%M'`;

chomp($time);
print $time;
}

my $old_fh = select(STDOUT);
$| = 1;
select($old_fh);
init_cpus();
for (;;) {
print ISEP;
show_time();
print ISEP;
show_jabberinfo();
print ISEP;
show_temperature();
print ISEP;
show_mem_info();
print ISEP;
show_battery_info();
show_net_info();
print "\n";
sleep(IDLE);
}

There are my Icons : Icons.tar.gz

And this is a snap of my workspace:
Free Image Hosting at www.ImageShack.us

Thursday, July 31, 2008

ReadLeaf: research pane

Today, how I've wrote later, readleaf 0.1 was released and finished lazy stage - now it's a platform for research and implementation.
Both, MuiString and ReadLeaf has a one general idea, but MuiString is more deeper in implementation and some decisions need to be tested on other layer - quick and fast before this innovation will be implemented within MuiString and Jari overally.
ReadLeaf is a good start point for this type of research, I will use new way in development primary here - in area of the project.
I'm too lazy for repeations - you can see the general overview here - http://readleaf.berlios.de/concept.html
Currently already implemented:
  • redleafd
  • internal mm
  • basic research
Version 0.2 will be already with new features, now it's on the testing and development stage, but not so long from finish.

Monday, July 21, 2008

MuiString: Introduction to the architecture #1

Today we're have a many implementations of the microkernel architectures, but there are too similar and have many problems.
The first problem is a speed, the second one is a security.
Generally microkernel more secure than monolithic-based operating system, but with some restrictions, if you grow up speed, you are loosing in security.
But it's a general problems - more complicated thing - we're using C/C++/ObjC to implement architecture, and there are language takes a many time and limits in the implementing.
My general idea is to use a functional programming language - and I've choose scheme - it's better, simply.
Look for the block diagram:
MuiString separated to the three logical parts, the first low two layers implemented on C (or on Cext in future), the third layer implemented on C/Cext and on scheme itself.
All hardware specific things are hidden in the MuiString.
All services should be implemented on scheme, yes, we're can use C-written servers and libs (it should be done for liblinux/libposix), but in general case all other will be implemented on scheme and ran on scheme VM.
All IPC will be operate via scheme forms - in this case all security models will be implemented without IPC calls restrictions, and it can be made on the VM (or language) level.
There are several security models and several objects on the higher level:
  • Trusted servers
  • Key signed
  • Group politics
Trusted servers can allow secure transmit via determined servers, for example - you trust to the TCP/IP server, LAN server also trust it, but there are no directions from you to the LAN server, but LAN server and you can get access to execute scheme forms from/on LAN server, because there are trusted via TCP/IP server.

I will write more researching results in the next post.

Friday, July 18, 2008

Redleaf: new plans and ways

As of redleafd 0.1beta release (now it can be used for some purposes with sure) I'm take an idea, I want to implement some features for my work - it's a time sharing, job statistics, projects states etc ...
I've decided to make it via web, yes, in case of public (but restricted use) using.
What the deal I'm talking about ?
There are a complete service for each one who cares and working on open-source project, scheduling community events, working time and want to make a proof of participating and real developer state.
For example - I have a many mails from people who wants me to take they like a developers to open source project, in the past I've including everybody, but there are no effect on this - nobody works, people was enlisted and nothing else.
On real practice - I want to take a view to each of candidate to participate in project via this service. There are no service for it yet.
Also, there are a good thing for employer to avoid time loose with non right mans.
eh, you can told me about linkedin - linkedin is not really make a proof of your skills and jobs - it's suck.
So, it was a some non-technical introduction ...
I'm reserving 4-5 hours per week for redleaf, and I want to introduce technologies will used for this project:
  • - httpd - redleafd (small and fast)
  • - scheme_modula (module for the redleaf that suppose to run scheme code as quick as it possible)
  • - web ui software written on scheme
  • - parsing/collecting server side daemons on python || scheme (it depends on my research with libs)
In this case I will release in near time redleaf 0.1 (beta version can be found here - http://prdownload.berlios.de/readleaf/redleaf-0.1beta.tar.gz ), that will supports basic http stuff only.
After those I'm planning to reorganize architecture and rewrite some code, to support dynamic modules and so on for flexibility, the next stage will be a set of modules. After this stage I will implement scheme_modula and starts to write web ui and server side daemons.
In this case I'm need to anybody who knows any of the following - or all of this stuff:
  • - C and UNIX IPC
  • - Data structures and memory management techniques
  • - Scheme
  • - any of - cvs/git/svn/arch/etc ... on really good level
  • - Python
  • - html/css and optionally javascript
  • - Gimp and some creative techniques for image/icons creating
Benefits you will get working on this project: you can become famous (maybe, who knows?), you can update your skills on programming and especially on scheme programming - on real practice, you will have a short and cool name for imap account - and invitation to the newly created service ... hmm like authors.
I'm looking for you - contact me via jabber - tirra at njs.netlab.cz

Thank you.

Tuesday, July 15, 2008

Tips'n'Tricks: GCC useful macros for debugging

Continuing my series for newbies/beginners I want to told about gcc macros useful for debugging.
Everytime on C you have deal with memory, and very big part of bugs are memory managing related.
You must know differents ways to decide question with it, wrappers to general mmap/malloc/munmap/free functions, implement your own allocator (if you really know what you're doing).
Anyway, it's better to know without debugger (just use stdout to make this deal) when you are allocate and freed memory. GCC has a several really useful macros for this.
For example let's write a simple example with free() function:

void *__my_free(char *file,int line,char *function,void *p)
{
if(p) free(p);
else {
fprintf(stderr,"Trying to free nil pointer.\n");
fprintf(stderr,"At `%s:%d' via '%s'\n",file,line,function);
}

return NULL;
}

It's really a big shit deal to point everywhere info about function, line and file ;)
Just use this macro:

#define my_free(p) __my_free(__FILE__,__LINE__,(char *)__FUNCTION__,p)

This is all, for more detailed documentation see gcc manual.

Wednesday, July 02, 2008

Research: new ideas to system development

Doing some research on operating systems design you can choose the kernel model and in this case you can expect that microkernel is more stable, powerful and flexible compairing with monolithic design, exokernels are too platform specific and more complicable for application level platforms (i.e. embedded systems with too limited functionality). But like a bonus you will got the new area of research in this area - choosing and developing an instruments for implementation.
On this area, in my opinion, are old and good instrument is a pure C language for microkernel, for low level. But in case of many reasons C development has a long time for something bigger than microkernel, for microkernel you can extend C with macros or write your own preproccessor to extend C (like my project extC). This is good and right, but for microkernel servers and user level is better to use something else, more powerful with paradigms and more easy to develop.
It's not C++, not only in case of my hate to pluses, there are no reason to use C++ in any kind of development, C++ contain many ugly stuff and it has an ugly design overally. There are ObjectiveC, but this language will not decide our wishes.
I'm looking to functional programming languages - this way is more powerfull, well-designed lisp-like language is really simple to implement, they all has a simple syntax - and learning didn't takes a long time - it's intended to be meta-level development.
With its powerful I'm thinking about crazy things - what about to design a several DSL that can be simply implemented on Lisp/Scheme/Haskell , for different types of microkernel servers.
In example, you can research for often used language features and constructions that required for implement a filesystem, or block device driver, or network device driver etc...
I'm thinking to go deeper in this area after MuiString will ran. I promise to make a deep research, implement expiremental DSLs for this purposes and test it for perfomance and other things.
Be updated, take a look to functional programming of your research - it's a wonderful world of new features and paradigms.

Memory management - buddy system trick.

How I wrote before, on low level we're need a simple and fast allocator with minimal external fragmentation. It was buddy system. I've used a binary buddy in case of simple and clean code and perfomance.
But we're need to store a free buddies list, but we haven't any allocators lower and we're cannot allocate something for it, and we're cannot create linked list of pointers to the blocks and chunks - and it's not so clever - the really big overdraft on it.
Theory:
I've decide that I can use a bitmap in this case, for grow up speed I will use a bitmap for each buddy list level in this case for first level we're need just 1 bit per attribute, for second 2 bits per attribute ... and so on. Also we're need to make a simple initialization and keep information about separating. In this case we're using 2 bits per buddy block, I've called them - the first one is negative bitmap, the second one is positive bitmap.
What are they means? The first bit attribute (negative) points that if the bit is set it's a free block, if not it's used (or unmapped) block. Second bit attribute (positive) points that if the bit set it's not separated block, otherwise is. In this model we're simply full negative bitmap with 0x0and positive bitmap with 0xffffffff, and how you can understand we will use unsigned integer 32bit sized ones for bitmap.
Make a simple calculations and you will get a good news - for map buddy with 16-parts you need 64bits or 8 bytes, isn't pretty?
Implementation:
So, the first I will declare the general structure that will describe buddy system:

typedef struct __bbuddy_type {
uint32_t *pbmp;
uint32_t *nbmp;
uint32_t pn;
} bbuddy_t;

How you can see there are two pointers and what the neck ?
So, I'll explain it - on low level you need to take a pointer (determining the size you need) and use it for your first buddy - it's simply than something else. Also, I store buddy_t first and after it I'm storing uint32_t data.
Also we're need an macro that will calculate the overall size to store the buddy system, let's take it:

#define bbuddy_size(n) (((((n/32)==0) ? 1 : ((n/32>1) ? (n/32)+2 : n/32+1))*(2*sizeof(uint32_t)))+\
sizeof(bbuddy_t))


Explaining it, for parts that bigger than 1/32 of buddy mapped area we're need just one uint32_t , for 1/32 yet another one, and for smaller parts working a general rule to calculate size. Like in squares roots calculation ;)
Also you will need for several useful macros that will calculates index of pointer and bit position within bitmap area:

#define bbuddy_indexp(p,n) ((p/32 > 1) ? ((p/32)+(n/32)) : p/32)
#define bbuddy_indexbn(n) ((n/32>0) ? n%32 : n)

The first macro will calculate index to choose correct uint32_t data, and second one to choose a bit position, be careful using this macros as is not a good practice, I will show examples of using its.
In the implementation explanation I don't want to show you all the source code, it's a simple - you can implement it yourself without any kind of problems.
But there are some useful code snippets I'll show. 
The first point on implementation is initialization of buddy system, assign a correct pointers for bitmaps, init first block free. Here be careful with pointers shifting deals, I will show you the simple one, that works correctly, but don't forgot that C operator '+' on pointers shifts pointers with the size of  pointer type.
I've used char* - it's a clean and transparent to understand:

uint8_t bbuddy_init(bbuddy_t *b,uint32_t max_part)
{
int yy=(max_part/32)*2,i;
char *ptr=(char*)b;

if(b && max_part) {
ptr+=sizeof(bbuddy_t);
b->pbmp=(uint32_t*)ptr;
ptr+=(sizeof(uint32_t)*((max_part/32 > 1) ? (max_part/32)+2 : (max_part/32)+1));
b->nbmp=(uint32_t*)ptr;
} else
return 1;

b->pn=max_part;

max_part/=32;

for(i=0;i<yy;i++) {
b->nbmp[i]=nil;
b->pbmp[i]=fil;
}

/* init first */
b->nbmp[0] |= (1 << 0);
b->nbmp[0] |= (1 << 1);

return 0;
}

NOTE: nil it's a macro defined to 0x0 and fil is a macro defined to 0xffffffff.
Here we go ... we're a correctly init buddy system structure.
Now, I want to wrote about allocations/splitting/freeing specifics of this implementation.
I've implement an allocation function with mind that I've giving a part number of buddy system and it's trying to return me a number of avialable and allocated part. Look below:

static uint32_t __bbuddy_block_alloc(bbuddy_t *b,uint32_t align,uint8_t m_flag)
{
uint32_t p_indx=align/32;
uint32_t n_indx=0,i=0,o=0;

if(p_indx) {
for(i=0;i<p_indx;i++) {
if(b->nbmp[p_indx+i]!=0x0)
goto __is_free_long;
}
m_flag++;
return __bbuddy_block_alloc(b,align/2,m_flag);
}

if(!p_indx) { /* checking small layers, big blocks */
o=align*2;
for(i=align;i<o;i++)
if((b->nbmp[p_indx] & (1 << i)) && !m_flag) {
b->nbmp[p_indx] &= ~(1 << i); /* used */
b->pbmp[p_indx] |= (1 << i); /* not separated */
return i-align;
} else if((b->nbmp[p_indx] & (1 << i)) && m_flag) {
b->nbmp[p_indx] &= ~(1 << i); /* used */
b->pbmp[p_indx] &= ~(1 << i); /* separated */
/* mark childs free */
align*=2; i*=2;
p_indx=align/32;
n_indx=bbuddy_indexbn(i);
b->nbmp[p_indx] |= (1 << n_indx);
b->nbmp[p_indx] |= (1 << (n_indx+1));
b->pbmp[p_indx] |= (1 << n_indx);
b->pbmp[p_indx] |= (1 << (n_indx+1));

m_flag--;
return __bbuddy_block_alloc(b,align,m_flag);
}
if(i<2)
return ENOBLOCK;
else {
m_flag++;
return __bbuddy_block_alloc(b,align/2,m_flag);
}
}

__is_free_long:
while(o<32) {
if((b->nbmp[p_indx+i] & (1 << o)) && !m_flag) { /* yep, found */
b->nbmp[p_indx+i] &= ~(1 << o); /* used */
b->pbmp[p_indx+i] |= (1 << o); /* not separated */
return (p_indx > 1) ? (((p_indx+i)-2)*32)+o : o;
}
else if((b->nbmp[p_indx+i] & (1 << o)) && m_flag) { /* make sep */
b->nbmp[p_indx+i] &= ~(1 << o); /* used */
b->pbmp[p_indx+i] &= ~(1 << o); /* separated */
/* mark childs free */
align*=2; p_indx=align/32; o*=2;
p_indx=bbuddy_indexp(align,o);
n_indx=bbuddy_indexbn(o);
b->nbmp[p_indx] |= (1 << n_indx);
b->nbmp[p_indx] |= (1 << (n_indx+1));
b->pbmp[p_indx] |= (1 << n_indx);
b->pbmp[p_indx] |= (1 << (n_indx+1));

m_flag--;
return __bbuddy_block_alloc(b,align,m_flag);
}
o++;
}


return 0;
}

How you can see there are difference between 1/16 and bigger parts - I've showed it, it's separated via source code implementation in case of making additional checking and different calculation in both situations, you can split there parts into one to make code lines counter smaller , but it doesn't give any perfomance effect (tested).
Freeing buddy block must be assigned with splitting buddy into bigger block if possible, I've implement this via recursive separate function to make a lightweight to read release function, also I will point to indexes calculations here. 
And I want you to understand, I'm giving to release function number of smaller blocks like offset to release, after those I'm calculating possible variants of blocks can be and if found I'm releasing it, and only after it I'm calls my splitter function. Also, I don't include additonal checking code, make it yourself ;), look below:

static uint32_t __bbuddy_block_release(bbuddy_t *b,uint32_t num,uint32_t i)
{
uint32_t p_indx,n_indx;
uint32_t layer=b->pn,ls=layer,a=0;

/* first look up on higher possible layer
* if there are now, look deeper
*/

if(num>b->pn)
return EINVALIDINDX; /* error encount */

while(ls) { ls/=2; a++; }
if(i==0) {
for(i=(a-1);i>0;i--) {
if(num%2) break;
else num/=2;
}
}

layer=(1 << i);

n_indx=(layer<32) ? (num+layer) : bbuddy_indexbn(num);
p_indx=bbuddy_indexp(layer,num);
if(!(b->nbmp[p_indx] & (1 << n_indx)) && (b->pbmp[p_indx] & (1 << n_indx))) {
b->nbmp[p_indx] |= (1 << n_indx); /* mark free */
return __bbuddy_split_up(b,layer,num);
} else if(!(b->nbmp[p_indx] & (1 << n_indx)) && !(b->pbmp[p_indx] & (1 << n_indx))) { /* going deep */
i++;
if(i>=a)
return EBUDDYCORRUPED;
else
return __bbuddy_block_release(b,num*2,i);

}

return 0;
}

In case of my initialization and implementation of bitmap, I'm starting to look up for the block from the biggest blocks, because in othercase there are will be errors on cleanly initied bitmap and buddy will corruped.
Also, I don't want to describe my splitter function and I will not show it's source code - it's a trivial too like others.
Be patient, on my code (I wrote it and tested within 1-2 hours) some checks is absent, and some code I've specially removed - take your brains on working way ;)
Like API functions I've made a wrapper to hide all recursion in static functions, and with assign of initial counters values.
On next post I will try to explain how we're can use this abstraction to allocate real pointers, or you can think yourself and assume this method - it's a too trivial ;)

Monday, June 30, 2008

Memory management - low allocator base - binary buddy.

As I intended to memory managers implementing, I decide to write here about several techniques about this.
I don't interested on allocators in uspace now. I want to describe some tips and tricks on memory management while you haven't anything - just raw gdt/tss/ so on and raw addresses.
On low level of memory management and allocation system we're need to have a simple and fast memory allocator, it must avoid external fragmentation as strong as it possible.
There are one good allocator that doesn't sick with big external fragmentation - buddy system. You can find many it's types, but I'd like binary type - it's a very simple in calculation (that really needs).
Some words about buddy system... Buddy system is a such system that based on buddy relations for splitting memory areas. This system has several limitation - you must know deep of separation, I mean how much blocks maximally can contents buddy itself, and overally it can maps fixed memory area size (but it can be depends on implementation). The goal of this technique is to find free block aligned to requested size, when you are looking for some block size - you will separate block with bigger size and so on, while you didn't finf more situable block size. Look for illustrations: 
buddy system explanation
Fig. 1

The first bar shows clean buddy system without any allocated block (4096 bytes). When we're requesting to allocate block with size 512 byte we're separate zone to two blocks, and one of this zone separate we're separate too and use one of them - like it shown on the second bar. If we're request to allocate three more 512-sized block we will got the picture displayed on third bar.
It's a good and relativetly fast methodics, but has many restrictions - for example assume that your buddy system has 16byte-sized minimal blocks - and you request 10 bytes - so, you will get a wasted space - and so on - it's an inernal fragmentation. Be sure - you can align block sizes to other numbers , like you want and depend on your target, but anyway it will not safe to use buddy for all allocations.
Another point is a free/busy/separated blocks list storing - on low level you cannot use binary trees in case that they need to have some memory allocation technique already, usually for this used simple pointers lists, but it's a worse practice.
On the next post about memory management I will describe my solution of this problem with some useful code snippets.

Friday, June 27, 2008

Protest award domain name nativization from ICANN

So, there are bad news, no ICANN supports 'internalization' of domain names, now it's a possible to register a domain with your native language.
Due to many reasons - I decide to apply a protest for it - it's nothing, but maybe you will be participate on this.
And so on - I'll not post anything on languages differs from english, no jabber/blog/boards/sms/emails messages on non english from tomorrow !
I don't want to make a freedom to spooffing and idiotic things.

Participate if it possible.

I can feel your skeptics looks, yes - I'm just man and I don't have a voice in ICANN, but assume if there are many people like me? You know - world is small ;) And there are just time need ... and this protest will be effective. But anyway, if you will do nothing with it, in future with idiotic domains you will told yourself - "fuck'em up, I don't participate in protest, maybe my voice can be useful at there times ... shit shit shit" - feeling difference - take a voice, participate in this protest, control your life!

If you will participate, please comment here - thank you!

Tuesday, June 24, 2008

MuiString higher memory management

I've made some researching and emulation (not so serios, but representative) about memory management in microkernel OS.
Many kernels does memory management fully in kernel space, others separate it and offer non-trivial API for doing this in userspace.
We're have many restrictions - security and performance. If you will targeting to one of this properties you will loose on other. If you want to have a very strong and secure mechanism you will make a many context switching within kernel and user spaces - it will slow down your system perfomance, if you will don't care about security you will make it faster ...
I decide to make a basics virtual memory manager operations within kernel space, and offer simple API (just 4 calls) - address_space_get(), address_space_set(), address_space_alloc(), address_space_release(). And ... bind page fault exception to userspace area virtual mm server.
In this scheme microkernel just mark/unmark address space, it doesn't makes a check (and it will works fast) , and microkernel doesn't care about page fault exception - it's a server headache.
The security implemented on userspace - with ACL server that cannot be exchanged - like other varios servers (you must load its via multiboot modules way), all requests to ACL cached to the IPC cache server (it cannot be exchanged too) to avoid premiary access violation checks and grow up speed of requests. On the figure below I've tried to show it graphically (I like this, but I don't like to make a graphics ...):
Figure. 1

User task just trying to take some virtual memory and extend it's address space - it's a deal of libs to make all job with calling of vmm server. Vmm server asks about access rights/limits/etc ... on ACL server, if all granted - vmm will allocate space for user task, if will be need - it will calls MuiString microkernel via simple API.

This structure allows to make secure and fast (compairing with some highly secured or highly fast microkernel systems) - it's a good design for implementing different models of memory allocations (real-time, preemption, so on ...)

Monday, June 23, 2008

Emacs #1 - saving your state after exit , and tabbar use

Often you need to restore your emacs session, but it's not a good way to load all buffer per start, just keep it.
Also, there are useful addition to emacs called tabbar.el it can keeps your buffers without its creating.
I don't want to write where you can find this file - if you are using debian you can find it out in emacs-goodies-el package.
So, the first step is to enable tabbar mode by default:

(tabbar-mode t)

After this I recommend to bind a keys for switch between tabs:

(global-set-key [(control shift w)] 'tabbar-forward)
(global-set-key [(control shift q)] 'tabbar-backward)
(global-set-key [(control shift e)] 'tabbar-forward-group)
(global-set-key [(control shift d)] 'tabbar-backward-group)

You can use your own key bindings depending on your choice and feel.
The second step is to use a desktop addition (that comes with emacs22):

(when (fboundp 'desktop-load-default)
(desktop-load-default)
(mapcar
(lambda (symbol)
(add-to-list 'desktop-globals-to-save symbol))
'((buffer-name-history . 100)
(dired-regexp-history . 20)
(extended-command-history . 100)
(file-name-history . 500)
(grep-history . 50)
(minibuffer-history . 100)
(query-replace-history . 60)
(read-expression-history . 60)
(regexp-history . 60)
(regexp-search-ring . 20)
(search-ring . 20)
(shell-command-history . 50)))
;;; (desktop-read)
)

(add-to-list 'desktop-locals-to-save 'buffer-file-coding-system)
(add-to-list 'desktop-locals-to-save 'tab-width)

(setq-default desktop-missing-file-warning nil)
(setq-default desktop-path (quote ("~")))
(setq-default desktop-save t)
(setq-default desktop-save-mode t)

(setq-default save-place t)

And this all, this code snippets from my ~/.emacs file.

Using Gnome ?! really with modifications ...

I'm using Gnome 2.xx in case of some features that I need.
The first, if you know, network-manager knows about many specifics of many Wi-Fi modules tricks, for example for my RaLink card (that cannot be changed in my notebook) - it's needed to be downed and after this up with new network settings. So, I'm using many wireless networks (office, pubs, train stations, passenger terminals, ...) - but other network managers can't operates with my card, doing many stuff manually isn't sounds good for me - I'm lazy...
If you are using Gnome you know the base minus of it - it's a default window manager - metacity, this wm cannot remember anything about windows position, size and other varios attributes.
Also, on other side there are tiled window managers, but its takes many time to make a sense on configs and features.
The better way is to use my old friend - Window Maker wm, there are simple setting up, and it has many look and features that can be offered in tiled managers.
It can be looks like on my screenshot - Free Image Hosting at www.ImageShack.us

QuickPost

So, but Gnome feature - changing window manager is deprecated and all settings made over a gconf was failed. Solution was found - I've create ~/.gnomerc file and add the following line -
export WINDOW_MANAGER=wmaker
This line helps for it.
Also you can change some things like abort nautilus loading etc ... It will safe your memory and will turn off features for idiots.

Friday, June 20, 2008

AMD64 #1 - Long Mode

Backing to old days the first tree of microkernel was targeted to the x86 (32bit), going deeper the parent of all post projects (ilix) was targeted to embedded hardware i.e. arm and one internal architecture that was 24 bit.
Nowadays we're have a public accessible and cheep 64bit long architecture, x86 continuing but with 64bit long extension, but on real - it's looks different.
AMD64
allows many good extended features compairing with basic x86 32bit long structure. To use AMD64 features on full filled hand we're must operate in long mode (amd64 specific mode).
On truth, long mode is a mixed mode i.e. it operates on 64-bit mode and compatibility mode at one time. It has self minuses - it's a flat memory model. But it has 64-bit addressing and we're don't need for tricks with extension from intel to use more than 4Gb address space addressing, that relatively ugly and looks like an ugly hack.
Like a microkernel developer and low developer at one time - the first problem is initialization.
I've read AMD64 documentation directly from AMD, but there are no anything to really help with it, not at all, but if you want to make a sense quickly it's not usable.
I've designed a trick with it, saying simply it consist from following steps :
32bit code:
  • - initialize stack pointer (regarding your boot method and loader, I'm using grub and multiboot)
  • - init bootstrap GDT
  • - jump to 'meet point' within existing GDT
  • - save parameters from grub (will be need on if you using grub)
  • - we're falled on 32bit protected mode (legacy mode on AMD64)
  • - check for varios CPU features (it must be made if you want to made all like it must be in good kernels)
  • - check for AMD64 long mode support is a really needed (you should do it, otherwise you can except some bug - I don't know why - check it if I correct)
  • - all is ok, - enabling 64bit page translations (regarding to documentation set - cr4.pae=1)
  • - setup pages tables
  • - enable long mode (via EFER reg - setting LME to 1)
  • - enable paging in long mode (it will activate long mode and we're falling to compatibility mode)
  • - just jump to your 64bit code
64bit code:
  • - do your stuff, have a lot of fun ... ;)
I'm sure that there are direct long mode switching, but for me it was more quickly to make it like I've describe.

Tuesday, June 17, 2008

MuiString introduction

Ok, I've told many information about Jari and so on ... But it was just a buzz words.
Now I want to present MuiString (mstring) microkernel project.
What is done?
- base structure
- low level stuff
How much time it will takes ? How long will I told about it without microkernel on legs ? Hm, so I think that this times ends in case of microkernel progress.

I promise to write more technical things here and ... look for links below -
MuiString homepage - http://mstring.berlios.de
MuiString wiki - http://mstring.berlios.de/wiki
I have a memory manager and core of scheduler in my sandbox, it's under testing and preparing to be committed to the general CVS repository.
Look for my messages here soon.

Thanks.

Wednesday, June 04, 2008

Web fun - redleaf

How I wrote before - I opened a new project just for fun - and now it has releases and it's working - http://redleaf.berlios.de
But there are no time for prolongate any active development - I've spent less than 10 hours for this, and in future this will so.
If you want to take my flash point on this project - contact me, I'll be glad for it.
Anyway, this project will be like my testing platform - and some kinds of tasks will be implemented within this and tested.

Decomposing big project, separating is better

You can find more information on the link in the post title.
Overally, following to the general idea - "separate all works and job to smaller ones" I decide to run microkernel separatly - like independed project.
This intended to be more effective, for example - currently I have EZA layer working for 60% (not so stable) and this was made after reorganization of the microkernel structure - and this just for less then 10 hours of normal works on the problem.
MString (MuiString) - is a name for Jari microkernel - and it's a new tag on this blog ;)
Now I'm thinking on diferent than C/Cext language for server space - it's a big flame, but I'm thinking that fully functional languages or partly functional is better than typical imperativies ones. Anyway, microkernel must be implemented on plain C - it's more comfortable language.