diff -Nru linux-2.4.20/.config linux-2.4.20-cabi/.config --- linux-2.4.20/.config 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/.config 2005-03-11 20:05:32.000000000 +0900 @@ -0,0 +1,886 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_X86=y +# CONFIG_SBUS is not set +CONFIG_UID16=y + +# +# Code maturity level options +# +# CONFIG_EXPERIMENTAL is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODVERSIONS=y +CONFIG_KMOD=y + +# +# Processor type and features +# +# CONFIG_M386 is not set +# CONFIG_M486 is not set +# CONFIG_M586 is not set +# CONFIG_M586TSC is not set +# CONFIG_M586MMX is not set +# CONFIG_M686 is not set +CONFIG_MPENTIUMIII=y +# CONFIG_MPENTIUM4 is not set +# CONFIG_MK6 is not set +# CONFIG_MK7 is not set +# CONFIG_MELAN is not set +# CONFIG_MCRUSOE is not set +# CONFIG_MWINCHIPC6 is not set +# CONFIG_MWINCHIP2 is not set +# CONFIG_MWINCHIP3D is not set +# CONFIG_MCYRIXIII is not set +CONFIG_X86_WP_WORKS_OK=y +CONFIG_X86_INVLPG=y +CONFIG_X86_CMPXCHG=y +CONFIG_X86_XADD=y +CONFIG_X86_BSWAP=y +CONFIG_X86_POPAD_OK=y +# CONFIG_RWSEM_GENERIC_SPINLOCK is not set +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_X86_L1_CACHE_SHIFT=5 +CONFIG_X86_HAS_TSC=y +CONFIG_X86_GOOD_APIC=y +CONFIG_X86_PGE=y +CONFIG_X86_USE_PPRO_CHECKSUM=y +CONFIG_X86_F00F_WORKS_OK=y +CONFIG_X86_MCE=y +# CONFIG_TOSHIBA is not set +# CONFIG_I8K is not set +# CONFIG_MICROCODE is not set +# CONFIG_X86_MSR is not set +# CONFIG_X86_CPUID is not set +CONFIG_NOHIGHMEM=y +# CONFIG_HIGHMEM4G is not set +# CONFIG_HIGHMEM64G is not set +# CONFIG_HIGHMEM is not set +# CONFIG_MATH_EMULATION is not set +# CONFIG_MTRR is not set +CONFIG_SMP=y +# CONFIG_MULTIQUAD is not set +# CONFIG_X86_TSC_DISABLE is not set +CONFIG_X86_TSC=y +CONFIG_HAVE_DEC_LOCK=y + +# +# General setup +# +CONFIG_NET=y +CONFIG_X86_IO_APIC=y +CONFIG_X86_LOCAL_APIC=y +CONFIG_PCI=y +# CONFIG_PCI_GOBIOS is not set +# CONFIG_PCI_GODIRECT is not set +CONFIG_PCI_GOANY=y +CONFIG_PCI_BIOS=y +CONFIG_PCI_DIRECT=y +CONFIG_ISA=y +CONFIG_PCI_NAMES=y +# CONFIG_EISA is not set +# CONFIG_MCA is not set +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +CONFIG_PCMCIA=y +CONFIG_CARDBUS=y +# CONFIG_TCIC is not set +# CONFIG_I82092 is not set +# CONFIG_I82365 is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +# CONFIG_HOTPLUG_PCI_COMPAQ is not set +# CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set +# CONFIG_HOTPLUG_PCI_IBM is not set +# CONFIG_HOTPLUG_PCI_ACPI is not set +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_KCORE_ELF=y +# CONFIG_KCORE_AOUT is not set +CONFIG_BINFMT_AOUT=y +CONFIG_BINFMT_ELF=y +CONFIG_BINFMT_MISC=y +CONFIG_PM=y +# CONFIG_APM is not set +CONFIG_CABI=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play configuration +# +CONFIG_PNP=y +CONFIG_ISAPNP=y + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_DEV_XD is not set +# CONFIG_PARIDE is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_CISS_SCSI_TAPE is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_LOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_RAM is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_BLK_STATS is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set +# CONFIG_BLK_DEV_MD is not set +# CONFIG_MD_LINEAR is not set +# CONFIG_MD_RAID0 is not set +# CONFIG_MD_RAID1 is not set +# CONFIG_MD_RAID5 is not set +# CONFIG_MD_MULTIPATH is not set +# CONFIG_BLK_DEV_LVM is not set + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +# CONFIG_NETFILTER is not set +# CONFIG_FILTER is not set +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_INET_ECN is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_VLAN_8021Q is not set + +# +# +# +# CONFIG_IPX is not set +# CONFIG_ATALK is not set + +# +# Appletalk devices +# +# CONFIG_DEV_APPLETALK is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set +# CONFIG_PHONE_IXJ is not set +# CONFIG_PHONE_IXJ_PCMCIA is not set + +# +# ATA/IDE/MFM/RLL support +# +CONFIG_IDE=y + +# +# IDE, ATA and ATAPI Block devices +# +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +# CONFIG_BLK_DEV_HD_IDE is not set +# CONFIG_BLK_DEV_HD is not set +CONFIG_BLK_DEV_IDEDISK=y +CONFIG_IDEDISK_MULTI_MODE=y +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDEDISK_VENDOR is not set +# CONFIG_BLK_DEV_IDEDISK_FUJITSU is not set +# CONFIG_BLK_DEV_IDEDISK_IBM is not set +# CONFIG_BLK_DEV_IDEDISK_MAXTOR is not set +# CONFIG_BLK_DEV_IDEDISK_QUANTUM is not set +# CONFIG_BLK_DEV_IDEDISK_SEAGATE is not set +# CONFIG_BLK_DEV_IDEDISK_WD is not set +# CONFIG_BLK_DEV_COMMERIAL is not set +# CONFIG_BLK_DEV_TIVO is not set +# CONFIG_BLK_DEV_IDECS is not set +CONFIG_BLK_DEV_IDECD=y +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_BLK_DEV_CMD640=y +# CONFIG_BLK_DEV_CMD640_ENHANCED is not set +# CONFIG_BLK_DEV_ISAPNP is not set +CONFIG_BLK_DEV_RZ1000=y +CONFIG_BLK_DEV_IDEPCI=y +CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_PCI_WIP is not set +# CONFIG_BLK_DEV_IDEDMA_TIMEOUT is not set +# CONFIG_IDEDMA_NEW_DRIVE_LISTINGS is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_AEC62XX_TUNING is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_WDC_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_AMD74XX_OVERRIDE is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_CMD680 is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_HPT34X_AUTODMA is not set +# CONFIG_BLK_DEV_HPT366 is not set +CONFIG_BLK_DEV_PIIX=y +CONFIG_PIIX_TUNING=y +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_PDC202XX is not set +# CONFIG_PDC202XX_BURST is not set +# CONFIG_PDC202XX_FORCE is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIS5513 is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_IDEDMA_IVB is not set +# CONFIG_DMA_NONPCI is not set +CONFIG_BLK_DEV_IDE_MODES=y +# CONFIG_BLK_DEV_ATARAID is not set +# CONFIG_BLK_DEV_ATARAID_PDC is not set +# CONFIG_BLK_DEV_ATARAID_HPT is not set + +# +# SCSI support +# +CONFIG_SCSI=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_SD_EXTRA_DEVS=40 +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_DEBUG_QUEUES=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_7000FASST is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AHA152X is not set +# CONFIG_SCSI_AHA1542 is not set +# CONFIG_SCSI_AHA1740 is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_IN2000 is not set +# CONFIG_SCSI_AM53C974 is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_DTC3280 is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_DMA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_GENERIC_NCR5380 is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_NCR53C406A is not set +# CONFIG_SCSI_NCR53C7xx is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_NCR53C8XX is not set +CONFIG_SCSI_SYM53C8XX=y +CONFIG_SCSI_NCR53C8XX_DEFAULT_TAGS=4 +CONFIG_SCSI_NCR53C8XX_MAX_TAGS=32 +CONFIG_SCSI_NCR53C8XX_SYNC=20 +# CONFIG_SCSI_NCR53C8XX_PROFILE is not set +# CONFIG_SCSI_NCR53C8XX_IOMAPPED is not set +# CONFIG_SCSI_NCR53C8XX_PQS_PDS is not set +# CONFIG_SCSI_PAS16 is not set +# CONFIG_SCSI_PCI2000 is not set +# CONFIG_SCSI_PCI2220I is not set +# CONFIG_SCSI_PSI240I is not set +# CONFIG_SCSI_QLOGIC_FAS is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_SEAGATE is not set +# CONFIG_SCSI_SIM710 is not set +# CONFIG_SCSI_SYM53C416 is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_T128 is not set +# CONFIG_SCSI_U14_34F is not set +# CONFIG_SCSI_ULTRASTOR is not set + +# +# PCMCIA SCSI adapter support +# +# CONFIG_SCSI_PCMCIA is not set + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set +# CONFIG_FUSION_BOOT is not set +# CONFIG_FUSION_ISENSE is not set +# CONFIG_FUSION_CTL is not set +# CONFIG_FUSION_LAN is not set + +# +# I2O device support +# +# CONFIG_I2O is not set +# CONFIG_I2O_PCI is not set +# CONFIG_I2O_BLOCK is not set +# CONFIG_I2O_LAN is not set +# CONFIG_I2O_SCSI is not set +# CONFIG_I2O_PROC is not set + +# +# Network device support +# +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +# CONFIG_BONDING is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_NET_SB1000 is not set + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +# CONFIG_SUNLANCE is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNBMAC is not set +# CONFIG_SUNQE is not set +# CONFIG_SUNGEM is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_LANCE is not set +# CONFIG_NET_VENDOR_SMC is not set +# CONFIG_NET_VENDOR_RACAL is not set +# CONFIG_AT1700 is not set +# CONFIG_DEPCA is not set +# CONFIG_HP100 is not set +# CONFIG_NET_ISA is not set +CONFIG_NET_PCI=y +# CONFIG_PCNET32 is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_AC3200 is not set +# CONFIG_APRICOT is not set +# CONFIG_CS89x0 is not set +# CONFIG_TULIP is not set +# CONFIG_DE4X5 is not set +# CONFIG_DGRS is not set +# CONFIG_DM9102 is not set +CONFIG_EEPRO100=y +# CONFIG_E100 is not set +# CONFIG_LNE390 is not set +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NE3210 is not set +# CONFIG_ES3210 is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_8139TOO_PIO is not set +# CONFIG_8139TOO_TUNE_TWISTER is not set +# CONFIG_8139TOO_8129 is not set +# CONFIG_8139_OLD_RX_RESET is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_SUNDANCE_MMIO is not set +# CONFIG_TLAN is not set +# CONFIG_TC35815 is not set +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_RHINE_MMIO is not set +# CONFIG_WINBOND_840 is not set +# CONFIG_NET_POCKET is not set + +# +# Ethernet (1000 Mbit) +# +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_MYRI_SBUS is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set +# CONFIG_FDDI is not set +# CONFIG_PLIP is not set +# CONFIG_PPP is not set +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# PCMCIA network device support +# +CONFIG_NET_PCMCIA=y +# CONFIG_PCMCIA_3C589 is not set +# CONFIG_PCMCIA_3C574 is not set +# CONFIG_PCMCIA_FMVJ18X is not set +CONFIG_PCMCIA_PCNET=y +# CONFIG_PCMCIA_AXNET is not set +# CONFIG_PCMCIA_NMCLAN is not set +# CONFIG_PCMCIA_SMC91C92 is not set +# CONFIG_PCMCIA_XIRC2PS is not set +# CONFIG_ARCNET_COM20020_CS is not set +# CONFIG_PCMCIA_IBMTR is not set +# CONFIG_PCMCIA_XIRCOM is not set +# CONFIG_PCMCIA_XIRTULIP is not set +CONFIG_NET_PCMCIA_RADIO=y +CONFIG_PCMCIA_RAYCS=y +# CONFIG_PCMCIA_NETWAVE is not set +# CONFIG_PCMCIA_WAVELAN is not set +# CONFIG_AIRONET4500_CS is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN is not set + +# +# Old CD-ROM drivers (not SCSI, not IDE) +# +# CONFIG_CD_NO_IDESCSI is not set + +# +# Input core support +# +# CONFIG_INPUT is not set +# CONFIG_INPUT_KEYBDEV is not set +# CONFIG_INPUT_MOUSEDEV is not set +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_SERIAL=y +# CONFIG_SERIAL_CONSOLE is not set +# CONFIG_SERIAL_EXTENDED is not set +# CONFIG_SERIAL_NONSTANDARD is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +CONFIG_MOUSE=y +CONFIG_PSMOUSE=y +# CONFIG_82C710_MOUSE is not set +# CONFIG_PC110_PAD is not set +# CONFIG_MK712_MOUSE is not set + +# +# Joysticks +# +# CONFIG_INPUT_GAMEPORT is not set + +# +# Input core support is needed for gameports +# + +# +# Input core support is needed for joysticks +# +# CONFIG_QIC02_TAPE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_AMD_RNG is not set +# CONFIG_INTEL_RNG is not set +# CONFIG_AMD_PM768 is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_FTAPE is not set +CONFIG_AGP=y +CONFIG_AGP_INTEL=y +CONFIG_AGP_I810=y +CONFIG_AGP_VIA=y +CONFIG_AGP_AMD=y +# CONFIG_AGP_AMD_8151 is not set +CONFIG_AGP_SIS=y +CONFIG_AGP_ALI=y +# CONFIG_AGP_SWORKS is not set +CONFIG_DRM=y +# CONFIG_DRM_OLD is not set + +# +# DRM 4.1 drivers +# +CONFIG_DRM_NEW=y +CONFIG_DRM_TDFX=y +# CONFIG_DRM_R128 is not set +CONFIG_DRM_RADEON=y +CONFIG_DRM_I810=y +CONFIG_DRM_I810_XFREE_41=y +# CONFIG_DRM_I830 is not set +# CONFIG_DRM_MGA is not set +# CONFIG_DRM_SIS is not set + +# +# PCMCIA character devices +# +# CONFIG_PCMCIA_SERIAL_CS is not set +# CONFIG_SYNCLINK_CS is not set +# CONFIG_MWAVE is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# File systems +# +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +CONFIG_AUTOFS4_FS=y +# CONFIG_REISERFS_FS is not set +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +# CONFIG_ADFS_FS is not set +# CONFIG_ADFS_FS_RW is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BEFS_DEBUG is not set +# CONFIG_BFS_FS is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_JBD_DEBUG is not set +# CONFIG_FAT_FS is not set +# CONFIG_MSDOS_FS is not set +# CONFIG_UMSDOS_FS is not set +# CONFIG_VFAT_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_JFFS_FS is not set +# CONFIG_JFFS2_FS is not set +# CONFIG_CRAMFS is not set +CONFIG_TMPFS=y +CONFIG_RAMFS=y +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +# CONFIG_JFS_FS is not set +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_NTFS_FS is not set +# CONFIG_NTFS_RW is not set +# CONFIG_HPFS_FS is not set +CONFIG_PROC_FS=y +# CONFIG_DEVFS_FS is not set +# CONFIG_DEVFS_MOUNT is not set +# CONFIG_DEVFS_DEBUG is not set +CONFIG_DEVPTS_FS=y +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX4FS_RW is not set +# CONFIG_ROMFS_FS is not set +CONFIG_EXT2_FS=y +# CONFIG_SYSV_FS is not set +# CONFIG_UDF_FS is not set +# CONFIG_UDF_RW is not set +# CONFIG_UFS_FS is not set +# CONFIG_UFS_FS_WRITE is not set + +# +# Network File Systems +# +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +CONFIG_NFS_FS=y +# CONFIG_NFS_V3 is not set +# CONFIG_ROOT_NFS is not set +CONFIG_NFSD=y +# CONFIG_NFSD_V3 is not set +# CONFIG_NFSD_TCP is not set +CONFIG_SUNRPC=y +CONFIG_LOCKD=y +# CONFIG_SMB_FS is not set +# CONFIG_NCP_FS is not set +# CONFIG_NCPFS_PACKET_SIGNING is not set +# CONFIG_NCPFS_IOCTL_LOCKING is not set +# CONFIG_NCPFS_STRONG is not set +# CONFIG_NCPFS_NFS_NS is not set +# CONFIG_NCPFS_OS2_NS is not set +# CONFIG_NCPFS_SMALLDOS is not set +# CONFIG_NCPFS_NLS is not set +# CONFIG_NCPFS_EXTRAS is not set +# CONFIG_ZISOFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_SMB_NLS is not set +# CONFIG_NLS is not set + +# +# Console drivers +# +CONFIG_VGA_CONSOLE=y +# CONFIG_VIDEO_SELECT is not set + +# +# Sound +# +CONFIG_SOUND=y +# CONFIG_SOUND_ALI5455 is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_CMPCI is not set +# CONFIG_SOUND_EMU10K1 is not set +# CONFIG_MIDI_EMU10K1 is not set +# CONFIG_SOUND_FUSION is not set +# CONFIG_SOUND_CS4281 is not set +# CONFIG_SOUND_ES1370 is not set +CONFIG_SOUND_ES1371=y +# CONFIG_SOUND_ESSSOLO1 is not set +# CONFIG_SOUND_MAESTRO is not set +# CONFIG_SOUND_MAESTRO3 is not set +# CONFIG_SOUND_FORTE is not set +# CONFIG_SOUND_ICH is not set +# CONFIG_SOUND_RME96XX is not set +# CONFIG_SOUND_SONICVIBES is not set +# CONFIG_SOUND_TRIDENT is not set +# CONFIG_SOUND_MSNDCLAS is not set +# CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set +# CONFIG_MIDI_VIA82CXXX is not set +# CONFIG_SOUND_OSS is not set +# CONFIG_SOUND_TVMIXER is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +# CONFIG_USB_DEVICEFS is not set +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_LONG_TIMEOUT is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_EHCI_HCD is not set +CONFIG_USB_UHCI_ALT=y +# CONFIG_USB_OHCI is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_BLUETOOTH is not set +# CONFIG_USB_MIDI is not set +CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_DATAFAB is not set +# CONFIG_USB_STORAGE_FREECOM is not set +# CONFIG_USB_STORAGE_ISD200 is not set +# CONFIG_USB_STORAGE_DPCM is not set +# CONFIG_USB_STORAGE_HP8200e is not set +# CONFIG_USB_STORAGE_SDDR09 is not set +# CONFIG_USB_STORAGE_SDDR55 is not set +# CONFIG_USB_STORAGE_JUMPSHOT is not set +# CONFIG_USB_ACM is not set +# CONFIG_USB_PRINTER is not set + +# +# USB Human Interface Devices (HID) +# +# CONFIG_USB_HID is not set + +# +# Input core support is needed for USB HID input layer or HIDBP support +# +# CONFIG_USB_HIDINPUT is not set +# CONFIG_USB_HIDDEV is not set +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set + +# +# USB Imaging devices +# +# CONFIG_USB_DC2XX is not set +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_SCANNER is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_CATC is not set +# CONFIG_USB_CDCETHER is not set +# CONFIG_USB_USBNET is not set + +# +# USB port drivers +# +# CONFIG_USB_USS720 is not set + +# +# USB Serial Converter support +# +# CONFIG_USB_SERIAL is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set + +# +# Bluetooth support +# +# CONFIG_BLUEZ is not set + +# +# Kernel hacking +# +# CONFIG_DEBUG_KERNEL is not set + +# +# Library routines +# +# CONFIG_ZLIB_INFLATE is not set +# CONFIG_ZLIB_DEFLATE is not set diff -Nru linux-2.4.20/Makefile linux-2.4.20-cabi/Makefile --- linux-2.4.20/Makefile 2002-11-29 08:53:16.000000000 +0900 +++ linux-2.4.20-cabi/Makefile 2005-03-11 20:05:18.000000000 +0900 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 4 SUBLEVEL = 20 -EXTRAVERSION = +EXTRAVERSION =-cabi KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) @@ -19,7 +19,7 @@ HOSTCC = gcc HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -CROSS_COMPILE = +CROSS_COMPILE =586- # # Include the make variables (CC, etc...) @@ -190,6 +190,7 @@ DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o DRIVERS-$(CONFIG_ISDN_BOOL) += drivers/isdn/vmlinux-obj.o +DRIVERS-$(CONFIG_CABI) += drivers/cabi/cabi.o DRIVERS := $(DRIVERS-y) diff -Nru linux-2.4.20/arch/i386/config.in linux-2.4.20-cabi/arch/i386/config.in --- linux-2.4.20/arch/i386/config.in 2002-11-29 08:53:09.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/config.in 2005-03-11 20:00:09.000000000 +0900 @@ -316,6 +316,8 @@ bool ' Use real mode APM BIOS call to power off' CONFIG_APM_REAL_MODE_POWER_OFF fi +bool 'CPU Accounting and Binding Interface support' CONFIG_CABI + endmenu source drivers/mtd/Config.in diff -Nru linux-2.4.20/arch/i386/kernel/entry.S linux-2.4.20-cabi/arch/i386/kernel/entry.S --- linux-2.4.20/arch/i386/kernel/entry.S 2002-11-29 08:53:09.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/kernel/entry.S 2005-03-11 20:00:09.000000000 +0900 @@ -211,6 +211,15 @@ movl %eax,EAX(%esp) # save the return value ENTRY(ret_from_sys_call) cli # need_resched and signals atomic test +#ifdef CONFIG_CABI + movl cabi_ret_with_reschedule_hook,%eax + testl %eax,%eax /* if (hook == 0) */ + je 1f /* yes, then skip it */ + call *%eax /* no, then call hook */ + testl %eax,%eax /* if (ret != 0) */ + jne ret_from_sys_call /* yes, then jump back */ +1: +#endif cmpl $0,need_resched(%ebx) jne reschedule cmpl $0,sigpending(%ebx) @@ -644,7 +653,7 @@ .long SYMBOL_NAME(sys_fremovexattr) .long SYMBOL_NAME(sys_tkill) .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sendfile64 */ - .long SYMBOL_NAME(sys_ni_syscall) /* 240 reserved for futex */ + .long SYMBOL_NAME(sys_ni_syscall) /* 240 keserved for futex */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_setaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* reserved for sched_getaffinity */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_thread_area */ @@ -657,6 +666,24 @@ .long SYMBOL_NAME(sys_ni_syscall) /* 250 sys_alloc_hugepages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_free_hugepages */ .long SYMBOL_NAME(sys_ni_syscall) /* sys_exit_group */ +#ifdef CONFIG_CABI + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 255 */ + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) + .long SYMBOL_NAME(sys_ni_syscall) /* 260 */ + .long SYMBOL_NAME(sys_cabi_account_create) + .long SYMBOL_NAME(sys_cabi_account_destroy) + .long SYMBOL_NAME(sys_cabi_account_bind_pid) + .long SYMBOL_NAME(sys_cabi_account_bind_pgid) + .long SYMBOL_NAME(sys_cabi_account_unbind) + .long SYMBOL_NAME(sys_cabi_account_get) + .long SYMBOL_NAME(sys_cabi_account_set) /* 267 */ + +#endif /* CONFIG_CABI */ .rept NR_syscalls-(.-sys_call_table)/4 .long SYMBOL_NAME(sys_ni_syscall) diff -Nru linux-2.4.20/arch/i386/lib/Makefile linux-2.4.20-cabi/arch/i386/lib/Makefile --- linux-2.4.20/arch/i386/lib/Makefile 2001-09-10 23:31:30.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/lib/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -9,7 +9,7 @@ obj-y = checksum.o old-checksum.o delay.o \ usercopy.o getuser.o \ - memcpy.o strstr.o + memcpy.o strstr.o udivdi3.o obj-$(CONFIG_X86_USE_3DNOW) += mmx.o obj-$(CONFIG_HAVE_DEC_LOCK) += dec_and_lock.o diff -Nru linux-2.4.20/arch/i386/lib/udivdi3.S linux-2.4.20-cabi/arch/i386/lib/udivdi3.S --- linux-2.4.20/arch/i386/lib/udivdi3.S 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/arch/i386/lib/udivdi3.S 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,396 @@ + .file "libgcc2.c" + .version "01.01" +gcc2_compiled.: +.section .rodata + .type __clz_tab,@object +__clz_tab: +.byte 0 +.byte 1 +.byte 2 +.byte 2 +.byte 3 +.byte 3 +.byte 3 +.byte 3 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 + .size __clz_tab,256 +.text + .align 4 +.globl __udivdi3 + .type __udivdi3,@function +__udivdi3: + subl $28,%esp + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + movl 56(%esp),%ebx + movl 60(%esp),%edi + movl 48(%esp),%eax + movl %eax,40(%esp) + movl 52(%esp),%edx + movl %edx,16(%esp) + testl %edi,%edi + jne .L25 + cmpl %edx,%ebx + jbe .L26 +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L26: + cmpl $0,56(%esp) + jne .L28 + movl $1,%eax + xorl %edx,%edx + divl %ebx + movl %eax,%ebx +.L28: + movl 16(%esp),%eax + xorl %edx,%edx +#APP + divl %ebx +#NO_APP + movl %eax,%edi + movl %edx,16(%esp) + movl 40(%esp),%eax +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L25: + cmpl %edi,16(%esp) + jae .L31 + xorl %edi,%edi + movl %edi,%esi + jmp .L30 + .align 4 +.L31: +#APP + bsrl %edi,%eax +#NO_APP + movl %eax,%esi + xorl $31,%esi + jne .L38 + cmpl %edi,16(%esp) + ja .L39 + cmpl %ebx,40(%esp) + jb .L45 +.L39: + movl $1,%esi + jmp .L45 + .align 4 +.L38: + movl $32,%ebp + subl %esi,%ebp + movl %esi,%ecx + sall %cl,%edi + movl %edi,20(%esp) + movl %ebx,%eax + movl %ebp,%ecx + shrl %cl,%eax + orl %eax,%edi + movl %esi,%ecx + sall %cl,%ebx + movl 16(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl %eax,36(%esp) + movl 16(%esp),%eax + movl %esi,%ecx + sall %cl,%eax + movl %eax,20(%esp) + movl 40(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl 20(%esp),%edx + orl %eax,%edx + movl %edx,16(%esp) + movl %esi,%ecx + sall %cl,40(%esp) + movl %edx,%eax + movl 36(%esp),%edx +#APP + divl %edi +#NO_APP + movl %eax,%esi + movl %edx,16(%esp) +#APP + mull %ebx +#NO_APP + movl %eax,%ebx + movl %edx,%edi + cmpl %edi,16(%esp) + jb .L44 + jne .L45 + cmpl %ebx,40(%esp) + jae .L45 +.L44: + decl %esi +.L45: + xorl %edi,%edi +.L30: + movl %esi,28(%esp) + movl %edi,32(%esp) + movl 28(%esp),%eax + movl 32(%esp),%edx + popl %ebx + popl %esi + popl %edi + popl %ebp + addl $28,%esp + ret +.Lfe1: + .size __udivdi3,.Lfe1-__udivdi3 + .ident "GCC: (GNU) 2.8.1" diff -Nru linux-2.4.20/drivers/Makefile linux-2.4.20-cabi/drivers/Makefile --- linux-2.4.20/drivers/Makefile 2002-11-29 08:53:12.000000000 +0900 +++ linux-2.4.20-cabi/drivers/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -8,7 +8,7 @@ mod-subdirs := dio hil mtd sbus video macintosh usb input telephony sgi ide \ message/i2o message/fusion scsi md ieee1394 pnp isdn atm \ - fc4 net/hamradio i2c acpi bluetooth + fc4 net/hamradio i2c acpi bluetooth cabi subdir-y := parport char block net sound misc media cdrom hotplug subdir-m := $(subdir-y) @@ -41,6 +41,8 @@ subdir-$(CONFIG_ISDN_BOOL) += isdn subdir-$(CONFIG_ATM) += atm subdir-$(CONFIG_FC4) += fc4 +# CABI +subdir-$(CONFIG_CABI) += cabi # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch subdir-$(CONFIG_HAMRADIO) += net/hamradio diff -Nru linux-2.4.20/drivers/cabi/%%386CABI.txt linux-2.4.20-cabi/drivers/cabi/%%386CABI.txt --- linux-2.4.20/drivers/cabi/%%386CABI.txt 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/%%386CABI.txt 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,19 @@ +-Makefile +-init/main.c +-include/linux/sched.h +void (*cabi_schedule_hook)(struct task_struct *, struct task_struct *); + kernel/sched.c + +int (*cabi_ret_with_reschedule_hook)(struct pt_regs regs); + arch/i386/kernel/entry.S +-kernel/sched.c +-arch/i386/kernel/entry.S + . add cabi_ret_with_reschedule_hook + . add system call entries +- include/asm-i386/unistd.h + . add _NR_cabi_* +-include/linux/sys.h +-kernel/fork.c +-kernel/exit.c +-kernel/ksyms.c + diff -Nru linux-2.4.20/drivers/cabi/Makefile linux-2.4.20-cabi/drivers/cabi/Makefile --- linux-2.4.20/drivers/cabi/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,16 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + +O_TARGET := cabi.o + +obj-y = cabi_init.o cabi_account.o cabi_timer.o cabi_sched.o cabi_isr.o cabi_signal.o + +obj-$(CONFIG_PROC_FS) += cabi_procfs.o + +include $(TOPDIR)/Rules.make diff -Nru linux-2.4.20/drivers/cabi/cabi_account.c linux-2.4.20-cabi/drivers/cabi/cabi_account.c --- linux-2.4.20/drivers/cabi/cabi_account.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_account.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,1770 @@ + /* + * linux/drivers/cabi/cabi_account.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * static variables for accounting + */ +cabi_account_t cabi_current_account; +struct list_head cabi_account_head; +cabi_account_t cabi_current_overload_account; +cpu_capacity_t cabi_account_current_capacity; +int last_cabi_id = 0; +int init_timer_flag; + +/* + * struct regist list for process group. + */ +struct rglist { + int count; + pid_t pid; + struct task_struct *tsk; + struct list_head rg_link; +}; +typedef struct rglist *rglist_t; +struct list_head rglist_head; + +extern long sys_setpgid(pid_t pid, pid_t pgid); +extern rwlock_t tasklist_lock; + +cabi_account_t +search_cabi(unsigned long cabi_id) +{ + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + + cabi_list = &cabi_account_head; + while (!list_empty(cabi_list)) { + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + if (cabi->cabi_id == cabi_id) + break; + + cabi_list = cabi_list->next; + if (cabi_list == &cabi_account_head) { + cabi = NULL_ACCOUNT; + break; + } + } + return cabi; +} + +void +cabi_account_init(void) +{ + INIT_LIST_HEAD(&cabi_account_head); + cabi_account_current_capacity = 0; + cabi_current_overload_account = NULL; +} + +int +get_cabi_id(void) +{ + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + int begin_cabi_id, cabi_id_error; + cabi_id_error = -1; + + begin_cabi_id = 0; + + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + + /* First AO create. */ + if ((cabi_list == &cabi_account_head) && (last_cabi_id == 0)) { + last_cabi_id = FIRST_CABI_ID; + return last_cabi_id; + } else { + if(last_cabi_id < CABI_ID_MAX) + last_cabi_id++; + } + while (!list_empty(cabi_list)) { /* Get cabi_id */ + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + /* cabi_id is full */ + if (last_cabi_id == begin_cabi_id) { + last_cabi_id = --begin_cabi_id; + return cabi_id_error; + } + /* selected cabi_id is for overload */ + if (OVERLOAD_CABI_ID == last_cabi_id) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is already used */ + if (cabi->cabi_id == last_cabi_id) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is MAX value */ + if (last_cabi_id >= CABI_ID_MAX) { + if (begin_cabi_id == 0) + begin_cabi_id = last_cabi_id; + last_cabi_id = FIRST_CABI_ID; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* next cabi list */ + cabi_list = cabi_list->next; + + /* all lists were searched. */ + if (cabi_list == &cabi_account_head) + break; + } + return last_cabi_id; +} + +void +overload_capacity(struct timespec *c, struct timespec *t, struct timespec *new_qc) +{ + cpu_capacity_quad_t qc, qt, new_nano_qc; + + /* re-calculate requested capacity */ + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + new_nano_qc = qt - qc; + memset (new_qc, 0x00, sizeof (struct timespec)); + new_qc->tv_sec = (long)(new_nano_qc / NANOSEC); + new_qc->tv_nsec = (long)(new_nano_qc - (cpu_capacity_quad_t)(new_qc->tv_sec * NANOSEC)); + +#ifdef DEBUG_CABI + printk("new_time.tv_sec (%ld), new_time.tv_nsec (%ld)\n", + new_qc->tv_sec, new_qc->tv_nsec); + printk("new_nano_time(c) %lld / period %lld\n", + new_nano_qc, qt); +#endif + +} + +static cabi_account_t +cabi_account_create(struct timespec *c, struct timespec *t, + cabi_param_data_t * p) +{ + int ret; + cabi_account_t cabi; + struct timespec new_qc; + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt; + long get_id = 0; + +#ifdef DEBUG_CABI + printk("cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + + /* if this is overload cabi, re-calculate parameters. */ + if (p->bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(c,t,&new_qc); + c->tv_sec = new_qc.tv_sec; + c->tv_nsec = new_qc.tv_nsec; +#ifdef DEBUG_CABI + printk("overload : cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + } + + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + capacity = CAPACITY_OF(qc, qt); + cabi_account_current_capacity = + capacity + cabi_account_current_capacity; + +#ifdef DEBUG_CABI + printk ("cabi_account_create: capacity(%lu.%02lu)\n", + CAPACITY_INT(capacity), CAPACITY_FRAC(capacity)); + +#endif + /* create an accounting object */ + if((cabi = malloc(sizeof (struct cabi_account))) == NULL) + return NULL; + bzero(cabi, sizeof (struct cabi_account)); + + /* memory copy */ + memcpy(&cabi->cabi_param, p, sizeof(cabi_param_data_t)); + if (cabi->cabi_param.bind_proc_type | IDLE_PROCESS) { + /* have there been overload cabi */ + if (!cabi_current_overload_account) { + cabi->cabi_id = OVERLOAD_CABI_ID; + cabi_current_overload_account = cabi; + } else { + /*XXXX Fix me XXXX*/ + /* It should be removed. */ + /* already existed. */ + free(cabi); + return NULL; + } + } else { + if((get_id = get_cabi_id()) < 0) { + free(cabi); + return NULL; + } else { + cabi->cabi_id = (unsigned int)get_id; + } + } + INIT_LIST_HEAD(&cabi->cpu_proc_list); + + memcpy (&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy (&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + +#ifdef CONFIG_PROC_FS + ret = cabi_proc_account_create(cabi); + if (ret) { + printk("Can't create cabi procfs. %d\n", ret); + free(cabi); + return NULL; + } +#endif + + /* + * if this is the first call as the requirement of reservation, + * we should set up cabi hooks. + */ + if (list_empty(&cabi_account_head)) { + /* enable scheduling hook */ + cabi_enable(); + } + list_add(&cabi->cpu_link, &cabi_account_head); + + /* calculate cpu ticks per capacity */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + +#ifdef DEBUG_CABI + printk("overload debug: %d\n", (int)cabi->cabi_id); + printk("cabi tick values : cpu_period_ticks(T) (%ld)" + "cpu_time_ticks(C) (%ld)\n", + (long) cabi->cpu_period_ticks, (long) cabi->cpu_time_ticks); +#endif + /* + * Let the account replenished from the next jiffy. + * See also cabi_timer.c:cabi_replenish_timer_create(). + * cpu_period_used_ticks = 0; + * cpu_period_available_ticks = 0; + */ + + /* init waitqueue */ + init_waitqueue_head(&cabi->depleted_wait); + + /* create entry as /proc/cabi/ */ + INIT_LIST_HEAD(&cabi->cpu_proc_list); + cabi->signal_block = SIGNAL_OFF; + +#ifdef DEBUG_CABI + printk("Signal : pid %d sig %d flag %d\n", + (int) CABI_SIGPID(cabi), (int) CABI_SIGNUM(cabi), + (int) CABI_SIGFLAG(cabi)); +#endif + if (cabi->cabi_param.term_act == CABI_TERM_SIGNAL) { + cabi->term_act_status = CABI_SIGNALBFR; + + if (!CABI_SIGPID(cabi)) { + /* if null, send default process */ + CABI_SIGFLAG(cabi) = CABI_SEND_DEFL; + } else { + CABI_SIGFLAG(cabi) = CABI_SEND_PID; + + } + } else if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + cabi->term_act_status = CABI_UNBLOCK; + } else { + /* error return */ + free(cabi); + return NULL; + } + return cabi; /* success */ +} + + +int +cabi_account_set(unsigned long cabi_id, struct timespec *c, + struct timespec *t, cabi_param_data_t * p) +{ + struct timespec new_qc; + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) { + /* cabi dose not exist. */ + return CABI_ENOEXIST; + } + +#ifdef DEBUG_CABI + printk("cabi_account_set: cabi(0x%x) " + "OLD: c(%ld,%ld) t(%ld,%ld) NEW: c(%ld,%ld) t(%ld,%ld)\n", + (int) cabi, cabi->cpu_time.tv_sec, cabi->cpu_time.tv_nsec, + cabi->cpu_period.tv_sec, cabi->cpu_period.tv_nsec, c->tv_sec, + c->tv_nsec, t->tv_sec, t->tv_nsec); +#endif + /* set terminate action */ + memcpy(&cabi->cabi_param, p, sizeof(cabi_param_data_t)); + + if(cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + cabi->term_act_status = CABI_UNBLOCK; + } else { + cabi->term_act_status = CABI_SIGNALBFR; + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->cabi_param.bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(c,t,&new_qc); + c->tv_sec = new_qc.tv_sec; + c->tv_nsec = new_qc.tv_nsec; +#ifdef DEBUG_CABI + printk("overload : cabi_account_create: c(%d,%d) t(%d,%d)\n", + (int) c->tv_sec, (int) c->tv_nsec, + (int) t->tv_sec, (int) t->tv_nsec); +#endif + } + + qc = c->tv_sec; + qc *= NANOSEC; + qc += c->tv_nsec; + qt = t->tv_sec; + qt *= NANOSEC; + qt += t->tv_nsec; + + /* calculate a new capacity */ + capacity = CAPACITY_OF(qc, qt); + printk("capacity : %lu\n", capacity); + + /* set current capacity */ + cabi_account_current_capacity = + capacity + cabi_account_current_capacity - cabi->cpu_capacity; + +#ifdef DEBUG_CABI + printk("cabi_account_set: jiffies(%lu) " + "capacity(%lu.%02lu) new total(%lu.%02lu)\n", jiffies, + CAPACITY_INT(capacity), CAPACITY_FRAC(capacity), + CAPACITY_INT(cabi_account_current_capacity), + CAPACITY_FRAC(cabi_account_current_capacity)); +#endif + + /* load the new parameters */ + memcpy(&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy(&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + + /* initialize available ticks */ + cabi->cpu_period_available_ticks = 0; + + /* calculate cabi ticks per capacity */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + + if (!list_empty(&cabi->cpu_proc_list)) { + /* cancel replenish timer */ + cabi_replenish_timer_cancel(cabi); + + /* reset a timer for it */ + cabi_replenish_timer_init(cabi, &cabi->cpu_period_ticks); + } + + return CABI_SUCCESS; /* success */ + +} + +static int +cabi_account_destroy(unsigned long cabi_id) +{ + int ret; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + /* if account has attached processes */ + if (!list_empty(&cabi->cpu_proc_list)) + /* process is still attached. */ + return CABI_EATTACHED; + + /* destroy timer */ + cabi_replenish_timer_cancel (cabi); + + /* return capacity */ + if (cabi->cpu_capacity >= cabi_account_current_capacity) { + cabi_account_current_capacity = 0; + } else { + cabi_account_current_capacity -= cabi_account_current_capacity; + } + + /* delete cpu_link */ + list_del(&cabi->cpu_link); + INIT_LIST_HEAD(&cabi->cpu_link); /* for sure */ + cabi->cabi_param.term_act = CABI_TERM_NONE; + +#ifdef CONFIG_PROC_FS + /* + * remove entry under /proc/cabi/ + * must be before cabi_resource_set_detach_account() + * since resource_set is reffered in cabi_proc_account_destroy() + */ + ret = cabi_proc_account_destroy(cabi); + if (ret) { + printk("Can't delete cabi procfs. %d \n", ret); + return CABI_ERROR; + } + +#endif + /* finally free a generic account object. */ + free(cabi); + + if (cabi_id == OVERLOAD_CABI_ID) + cabi_current_overload_account = NULL; + + return CABI_SUCCESS; /* success */ +} + +int +cabi_account_check_overload(void) +{ + cabi_account_t cabi = NULL_ACCOUNT; + unsigned long used_ticks; + unsigned long cpu_time_ticks; + long res; + + /* search overload cabi */ + if (!cabi_current_overload_account) { + return CABI_ENOEXIST; + } else { + cabi = cabi_current_overload_account; + } + + used_ticks = TICK2USEC(&cabi->cpu_period_used_ticks); + cpu_time_ticks = TICK2USEC(&cabi->cpu_time_ticks); + res = used_ticks - cpu_time_ticks; + +#ifdef DEBUG_CABI + printk("term act %x, cpu_period %lu, result %ld\n", + cabi->cabi_param.term_act, + TICK2USEC(&cabi->cpu_period_ticks), res); +#endif + /* compare the total used ticks with available ticks. */ + if (res <= 0) { +#ifdef DEBUG_CABI + printk("(-) C > used: cabi(0x%x) C (%lu) > used(%lu)\n", + (int) cabi, + (unsigned long) cpu_time_ticks, + (unsigned long) used_ticks); +#endif + cabi->overload |= CABI_IS_OVERLOAD; + } else { +#ifdef DEBUG_CABI + printk("(+) C < used: cabi(0x%x) C (%lu) < used(%lu)\n", + (int) cabi, + (unsigned long) cpu_time_ticks, + (unsigned long) used_ticks); +#endif + cabi->overload = CABI_IS_NULL; + } + return CABI_SUCCESS; +} + +static inline void +cabi_account_summation_of_used_ticks(cabi_account_t cabi, cpu_tick_t now) +{ + cabi->cpu_period_used_ticks += (*now - cabi->cpu_period_start_ticks); + cabi->cpu_period_start_ticks = *now; +} + +/* + * Replenish & Enforce a account + */ +void +cabi_account_replenish(cabi_account_t cabi, struct timespec *period) +{ + cpu_capacity_t c; + int is_running = 0; + long long ticks; + + *period = cabi->cpu_period; + + if (cabi->cpu_state & CABI_IS_RUNNING) { + cpu_tick_data_t now; + cabi_rdticks(&now); + cabi_stop_account(cabi, &now); + is_running++; + } + + /* if there is a bint in sigal_block flag, take off */ + if (cabi->cabi_param.term_act == CABI_TERM_SIGNAL) { + if (cabi->signal_block) { + cabi->signal_block = SIGNAL_OFF; + cabi->term_act_status = CABI_SIGNALBFR; + } + } else if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + if (cabi->term_act_status) + cabi->term_act_status = CABI_UNBLOCK; + } else { + /* bad parameter */ + cabi->term_act_status = CABI_UNKNOWN; + } + + /* check overload condition */ + if (!init_timer_flag) + init_timer_flag++; + else { + if (cabi_is_overload_account(cabi)) + cabi_account_check_overload(); + } + + /* update statistics */ + cabi->cpu_period_prev_used_ticks = cabi->cpu_period_used_ticks; + cabi->cpu_total_used_ticks += cabi->cpu_period_used_ticks; + c = CAPACITY_OF(cabi->cpu_period_used_ticks, cabi->cpu_period_ticks); + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + cabi->cpu_min_utilization = c; + } + + /* summation for average */ + cabi->cpu_average.total_utils += c; + cabi->cpu_average.total_count++; + +#ifdef DEBUG_CABI + printk("cabi_account_replenish: cabi(0x%x) used(%lu/%lu)" + "state(%x) next available(%lu)\n", + (int) cabi, + (unsigned long) cabi->cpu_period_used_ticks, + (unsigned long) cabi->cpu_period_available_ticks, + (int) cabi->cpu_state, + (unsigned long) cabi->cpu_period_available_ticks); +#endif + /* reset the used ticks */ + cabi->cpu_period_used_ticks = 0; + + /* + * If account was depleted, its processes were stopped on its wait + * list but remained in their original scheduling class. Wake them + * up if there are available ticks. + */ + if (!cabi_is_overload_account(cabi)) { + if (cabi->cpu_period_available_ticks > 0) { + cabi->cpu_state &= ~CABI_IS_DEPLETED; + wake_up(&cabi->depleted_wait); + + if (cabi->cabi_param.term_act == CABI_TERM_BLOCK) { + if (cabi->term_act_status) + cabi->term_act_status = CABI_UNBLOCK; + } + return; + } + } + cabi->cpu_state &= ~CABI_IS_DEPLETED; + ticks = cabi->cpu_period_used_ticks - cabi->cpu_period_available_ticks; + /* when excessiblely used */ + if (ticks > 0) { + cpu_tick_data_t next; + next = cabi->cpu_time_ticks - ticks; + if (next >= 0) { + cabi->cpu_period_available_ticks = next; + } else { + cabi->cpu_period_available_ticks = 0; + } + } else { + cabi->cpu_period_available_ticks = cabi->cpu_time_ticks; + } + + if (is_running) + cabi_start_account(cabi); +} + +void +cabi_account_enforce(cabi_account_t cabi) +{ + if (!(cabi_is_overload_account(cabi)) && + !(cabi->cpu_state & CABI_IS_DEPLETED)) { +#ifdef DEBUG_CABI + printk("cabi_account_enforce: cabi(0x%x) state(%x)\n", + (int) cabi, cabi->cpu_state); +#endif + cabi->cpu_state |= CABI_IS_DEPLETED; + } + /* + * Letting the depleted process sleep is done + * if depleted in cabi_isr.c:cabi_ret_with_reschedule(), + * which is called when a process exits the kernel. + */ +} + +void +cabi_account_sleep_on(cabi_account_t cabi) +{ + sleep_on(&cabi->depleted_wait); +} + +/* + * Start & Stop the account of CPU utilization. + */ +void +cabi_start_account(cabi_account_t cabi) +{ + long long next; + +#ifdef DEBUG_CABI + printk("cabi_start_account cpu_period_available_ticks(%d)\n", + (int) cabi->cpu_period_available_ticks); + printk("cabi_start_account cpu_period_used_ticks(%d)\n", + (int) cabi->cpu_period_used_ticks); +#endif + next = cabi->cpu_period_available_ticks - cabi->cpu_period_used_ticks; + cabi_rdticks(&cabi->cpu_period_start_ticks); + + switch (cabi->cpu_state) { + case CABI_IS_NULL: + cabi->cpu_state = CABI_IS_RUNNING; + cabi_enforce_timer_start(cabi, &next); + break; + case CABI_IS_DEPLETED: + cabi->cpu_state |= CABI_IS_RUNNING; + /* it's illegal state */ + break; + case CABI_IS_RUNNING: /* must not be so */ +#ifdef DEBUG_CABI + printk("start_account: CABI_IS_RUNNING\n"); + printk("cabi_start_account: cabi(0x%x) illegal state" + "(RUNNING)\n", (int) cabi); +#endif + cabi_enforce_timer_start(cabi, &next); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: // must not be so +#ifdef DEBUG_CABI + printk("statr_account: CABI_IS_RUNNING|CABI_IS_DEPLETED\n"); + printk("cabi_start_account: cabi(0x%x) illegal state" + "(RUNNING|DEPLETED)\n", (int) cabi); +#endif + break; + + default: /* unkown */ +#ifdef DEBUG_CABI + printk("cabi_start_account: " + "cabi(0x%x) unkown state(0x%x) next available(%lu)\n", + (int) cabi, (int) cabi->cpu_state, (unsigned long) next); +#endif + cabi->cpu_state = CABI_IS_RUNNING; + + if (next > 0) { + cabi_enforce_timer_start(cabi, &next); + } else { + cabi->cpu_state |= CABI_IS_DEPLETED; + } + break; + } +} + +static inline void +cabi_account_check_enforce(cabi_account_t cabi) +{ + if (!(cabi_is_overload_account(cabi)) && + cabi->cpu_period_used_ticks >= cabi->cpu_period_available_ticks) { +#ifdef DEBUG_CABI + printk("cabi_account_check_enforce: " + "enforce cabi(0x%x) used(%lu/%lu)\n", (int) cabi, + (unsigned long) cabi->cpu_period_used_ticks, + (unsigned long) cabi->cpu_period_available_ticks); +#endif + /* enforcing a account */ + cabi_account_enforce(cabi); + } +} + +void +cabi_stop_account(cabi_account_t cabi, cpu_tick_t now) +{ + + long long left; + + cabi_account_summation_of_used_ticks(cabi, now); + + switch (cabi->cpu_state) { + case CABI_IS_RUNNING: + cabi->cpu_state &= ~CABI_IS_RUNNING; + cabi_account_check_enforce(cabi); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: + cabi->cpu_state &= ~CABI_IS_RUNNING; + break; + + case CABI_IS_NULL: /* must not be so */ +#ifdef DEBUG_CABI + printk("stop_account: CABI_IS_NULL\n"); + printk("cabi(0x%x) illegal state(NULL)\n", (int) cabi); +#endif + cabi_account_check_enforce(cabi); + break; + case CABI_IS_DEPLETED: /* must not be so */ +#ifdef DEBUG_CABI + printk("stop_account: CABI_IS_DEPLETED\n"); + printk("cabi(0x%x) illegal state" + "(NULL|DEPLETED)\n", (int) cabi); +#endif + break; + default: /* unkown */ + left = + cabi->cpu_period_available_ticks - + cabi->cpu_period_used_ticks; +#ifdef DEBUG_CABI + printk("stop_account: default\n"); + printk("cabi_stop_account: cabi(0x%x) unkown state(0x%x) " + "left available(%lu)\n", + (int) cabi, (int) cabi->cpu_state, (unsigned long) left); +#endif + cabi->cpu_state = CABI_IS_NULL; + + if (left <= 0) { + cabi->cpu_state |= CABI_IS_DEPLETED; + } + break; + } +} + +int +cabi_account_attach(unsigned long cabi_id, struct task_struct *tsk) +{ + struct rs_proc_list *rs_proc; + cabi_account_t cabi = NULL_ACCOUNT; + + /* find the cabi address */ + if (cabi_is_overload_account(cabi)) { + cabi = cabi_current_overload_account; +#ifdef DEBUG_CABI + printk("cabi overload attach account %x\n", (int) cabi); +#endif + } + else { + if (!(cabi = search_cabi(cabi_id))) + /* did not exist. */ + return CABI_ENOEXIST; + } + + /* + * !!! Need to make sure cabi is really a account. + */ + TASK_ACCOUNT(tsk) = cabi; + + if((rs_proc = malloc(sizeof (struct rs_proc_list))) == NULL) + return CABI_ENOMEM; + bzero(rs_proc, sizeof (struct rs_proc_list)); + + if (list_empty(&cabi->cpu_proc_list)) { + /* If this process is first to bind AO, */ + /* create a timer for it. */ + cabi_replenish_timer_init(cabi, &cabi->cpu_period_ticks); + } + + rs_proc->rs_proc_task = tsk; + rs_proc->rs_proc_pid = tsk->pid; + { + unsigned long flags; + save_flags(flags); + cli(); + list_add(&rs_proc->rs_proc_list, &cabi->cpu_proc_list); + restore_flags(flags); + } + + /* attach! */ + if (cabi->cpu_period_start_ticks == 0 && + rs_proc->rs_proc_task == current) { + cabi_rdticks(&cabi->cpu_period_start_ticks); + } + /* if this is the current process, + * make it the current account and start accouting now */ + if (current == tsk) { + if (cabi_current_account != cabi) { + cabi_current_account = cabi; + } + cabi_start_account(cabi); + + if (cabi->cpu_state & CABI_IS_DEPLETED) { + cabi_account_enforce(cabi); + } + } + + return CABI_SUCCESS; +} + +int +cabi_account_detach(struct task_struct *tsk) +{ + cabi_account_t cabi = TASK_ACCOUNT(tsk); + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + if (rs_proc->rs_proc_pid == tsk->pid) { + break; + } + /* next element */ + proc_list = proc_list->next; + } + + if (rs_proc && rs_proc->rs_proc_pid == tsk->pid) { +#ifdef DEBUG_CABI + printk("account_detach_process: rs_proc(0x%x) pid(%d,%d)\n", + (int) rs_proc, tsk->pid, rs_proc->rs_proc_pid); +#endif + /* remove rs_proc from the list */ + list_del(&rs_proc->rs_proc_list); + + /* free rs_proc */ + INIT_LIST_HEAD(&rs_proc->rs_proc_list); + free(rs_proc); + } + + if (list_empty(&cabi->cpu_proc_list)) { + cabi->cpu_state &= ~CABI_IS_DEPLETED; + if (cabi == cabi_current_account) { + cabi_current_account = NULL_ACCOUNT; + } + cabi_replenish_timer_cancel(cabi); + } + + /* detach resource set from task */ + TASK_ACCOUNT(tsk) = NULL_ACCOUNT; + + if (tsk->state != TASK_RUNNING) { + wake_up(&cabi->depleted_wait); + } + + return CABI_SUCCESS; +} + +/* + * Linux proc file system interface + */ +#include +asmlinkage int +sys_cabi_account_create(struct cabi_uaccount *ucabi) +{ + + struct timespec c, t; + struct cabi_param p; + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + long time_sec, time_nsec, period_sec, period_nsec; + cpu_tick_data_t chk_time, get_time, max_time; + + chk_time = get_time = 0; + + /* permission check */ + if (current->euid) { + printk("cabi_create: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + /* parameter check */ + if (user_cabi.cabi_param.term_act <= CABI_TERM_NONE || + user_cabi.cabi_param.term_act >= CABI_TERM_UNKNOWN) + return CABI_EINVAL; + + if (user_cabi.cabi_param.bind_proc_type < BIND_NORMAL_PROC || + user_cabi.cabi_param.bind_proc_type > BIND_IDLE_PROC) + return CABI_EINVAL; + + if (user_cabi.cabi_param.term_act == CABI_TERM_SIGNAL) { + if (!(__cabi_find_process_by_pid(user_cabi.cabi_param.cabi_signal.pid))) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.pid < 0) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.sig < 0 || + user_cabi.cabi_param.cabi_signal.sig > 32) + return CABI_EINVAL; + } + + if (user_cabi.cpu_time.tv_sec < 0 || user_cabi.cpu_time.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_time.tv_sec == 0 && user_cabi.cpu_time.tv_nsec == 0) + return CABI_EINVAL; + + if (user_cabi.cpu_period.tv_sec < 0 || user_cabi.cpu_period.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_period.tv_sec == 0 && user_cabi.cpu_period.tv_nsec == 0) + return CABI_EINVAL; + + max_time = CABI_TICK_MAX / cabi_cpu_ticks_per_second * (cpu_tick_data_t)NANO_PER_MICRO; + time_sec = 0; + time_nsec = 0; + time_sec = user_cabi.cpu_time.tv_nsec / NANOSEC; + time_nsec = user_cabi.cpu_time.tv_nsec - time_sec * NANOSEC; + if (time_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_time.tv_sec)) + return CABI_EINVAL; + time_sec += user_cabi.cpu_time.tv_sec; + chk_time = (cpu_tick_data_t)time_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)time_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } + period_sec = 0; + period_nsec = 0; + period_sec = user_cabi.cpu_period.tv_nsec / NANOSEC; + period_nsec = user_cabi.cpu_period.tv_nsec - period_sec * NANOSEC; + if (period_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_period.tv_sec)) + return CABI_EINVAL; + period_sec += user_cabi.cpu_period.tv_sec; + chk_time = (cpu_tick_data_t)period_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)period_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: period_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } +#ifdef DEBUG_CABI + printk("sys_cabi_create: time_sec(%ld), time_nsec(%ld)\n", time_sec, time_nsec); + printk("sys_cabi_create: period_sec(%ld), period_nsec(%ld)\n", period_sec, period_nsec); +#endif + if (time_sec > period_sec) { + return CABI_EINVAL; + } else if (time_sec == period_sec) { + if (time_nsec > period_nsec) { + return CABI_EINVAL; + } + } + + chk_time = 0; + if (user_cabi.cpu_time.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_time.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%ldns) is too small.\n", + user_cabi.cpu_time.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_time.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_time.tv_nsec); +#endif + } + } + if (user_cabi.cpu_period.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_period.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period(%ldns) is too small.\n", + user_cabi.cpu_period.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_period.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_period.tv_nsec); +#endif + } + } + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.cabi_param.bind_proc_type == BIND_IDLE_PROC) { + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) != NULL) { + return CABI_CREATE_ERR; + } + if (user_cabi.cabi_param.term_act != CABI_TERM_SIGNAL) { + return CABI_EINVAL; + } + } + + /* parameter copy */ + memcpy (&c, &user_cabi.cpu_time, sizeof (struct timespec)); + memcpy (&t, &user_cabi.cpu_period, sizeof (struct timespec)); + memcpy (&p, &user_cabi.cabi_param, sizeof (struct cabi_param)); + +#ifdef DEBUG_CABI + printk("sys_cabi_account_create: c(%d), t(%d), term_act(%x)" + " bind_proc_type (%x)\n", + (int) c.tv_nsec, (int) t.tv_nsec, p.term_act, p.bind_proc_type); +#endif + if (!(cabi = cabi_account_create(&c, &t, &p))) + return CABI_CREATE_ERR; + + if(copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, sizeof (cabi_object_t))) { + cabi_account_destroy(cabi->cabi_id); + return CABI_EINVAL; + } + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_get(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct timespec rev_qc; + cabi_account_t cabi = NULL_ACCOUNT; + struct list_head *proc_list; + struct rs_proc_list *rs_proc = NULL; + + if (!ucabi) + return CABI_EINVAL; + + if (cabi_id == 0) + return CABI_EINVAL; /* invalid argument */ + + /* find cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + + /* next element */ + proc_list = proc_list->next; + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->cabi_param.bind_proc_type == BIND_IDLE_PROC){ + overload_capacity(&cabi->cpu_time, &cabi->cpu_period, &rev_qc); +#ifdef DEBUG_CABI + printk("new_cpu_time:%lu cpu_period:%lu\n", + rev_qc.tv_sec, rev_qc.tv_nsec); +#endif + if(copy_to_user(&ucabi->cpu_time, &rev_qc, + sizeof (ucabi->cpu_time))) + return CABI_EINVAL; + } else { + if(copy_to_user(&ucabi->cpu_time, &cabi->cpu_time, + sizeof(ucabi->cpu_time))) + return CABI_EINVAL; + } + + if(copy_to_user(&ucabi->cpu_period, &cabi->cpu_period, sizeof (ucabi->cpu_period))) + return CABI_EINVAL; + if(copy_to_user(&ucabi->cabi_param, &cabi->cabi_param, sizeof (ucabi->cabi_param))) + return CABI_EINVAL; + if(copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, sizeof (ucabi->cabi_id))) + return CABI_EINVAL; + + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_set(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + struct timespec t, c; + cabi_param_data_t p; + long time_sec, time_nsec, period_sec, period_nsec; + cpu_tick_data_t chk_time, get_time, max_time; + + chk_time = get_time = 0; + + /* permission check */ + if (current->euid) { + printk("cabi_set: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + /* parameter check */ + if (cabi_id == 0) + return CABI_EINVAL; /* Invalid argument */ + + if (user_cabi.cabi_param.term_act <= CABI_TERM_NONE || + user_cabi.cabi_param.term_act >= CABI_TERM_UNKNOWN) + return CABI_EINVAL; + + if (user_cabi.cabi_param.bind_proc_type < BIND_NORMAL_PROC || + user_cabi.cabi_param.bind_proc_type > BIND_IDLE_PROC) + return CABI_EINVAL; + + if (user_cabi.cabi_param.term_act == CABI_TERM_SIGNAL) { + if (!(__cabi_find_process_by_pid(user_cabi.cabi_param.cabi_signal.pid))) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.pid < 0) + return CABI_EINVAL; + if (user_cabi.cabi_param.cabi_signal.sig < 0 || + user_cabi.cabi_param.cabi_signal.sig > 32) + return CABI_EINVAL; + } + + if (user_cabi.cpu_time.tv_sec < 0 || user_cabi.cpu_time.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_time.tv_sec == 0 && user_cabi.cpu_time.tv_nsec == 0) + return CABI_EINVAL; + + if (user_cabi.cpu_period.tv_sec < 0 || user_cabi.cpu_period.tv_nsec < 0) + return CABI_EINVAL; + if (user_cabi.cpu_period.tv_sec == 0 && user_cabi.cpu_period.tv_nsec == 0) + return CABI_EINVAL; + + max_time = CABI_TICK_MAX / cabi_cpu_ticks_per_second * (cpu_tick_data_t)NANO_PER_MICRO; + time_sec = 0; + time_nsec = 0; + time_sec = user_cabi.cpu_time.tv_nsec / NANOSEC; + time_nsec = user_cabi.cpu_time.tv_nsec - time_sec * NANOSEC; + if (time_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_time.tv_sec)) + return CABI_EINVAL; + time_sec += user_cabi.cpu_time.tv_sec; + chk_time = (cpu_tick_data_t)time_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)time_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } + period_sec = 0; + period_nsec = 0; + period_sec = user_cabi.cpu_period.tv_nsec / NANOSEC; + period_nsec = user_cabi.cpu_period.tv_nsec - period_sec * NANOSEC; + if (period_sec > (long)(CABI_TIME_SEC_MAX - user_cabi.cpu_period.tv_sec)) + return CABI_EINVAL; + period_sec += user_cabi.cpu_period.tv_sec; + chk_time = (cpu_tick_data_t)period_sec; + chk_time *= NANOSEC; + chk_time += (cpu_tick_data_t)period_nsec; + if(chk_time > max_time) { +#ifdef DEBUG_CABI + printk("cabi_create: period_time(%llu nsec) is too large.\n", chk_time); + printk(" This system can be set up to %llu nsec. (MAX)\n", + max_time); +#endif + return CABI_EINVAL; + } +#ifdef DEBUG_CABI + printk("sys_cabi_set: time_sec(%ld), time_nsec(%ld)\n", time_sec, time_nsec); + printk("sys_cabi_set: period_sec(%ld), period_nsec(%ld)\n", period_sec, period_nsec); +#endif + chk_time = 0; + if (user_cabi.cpu_time.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_time.tv_nsec), + &chk_time); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time(%ldns) is too small.\n", + user_cabi.cpu_time.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_time.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_time changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_time.tv_nsec); +#endif + } + } + if (user_cabi.cpu_period.tv_sec == 0) { + nanosec2tick((cpu_tick_t) (&user_cabi.cpu_period.tv_nsec), + (cpu_tick_t) (&chk_time)); + if (chk_time == 0) { +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period(%ldns) is too small.\n", + user_cabi.cpu_period.tv_nsec); +#endif + get_time = cabi_cpu_ticks_per_second / MICROSEC; + if(cabi_cpu_ticks_per_second - MICROSEC * get_time) + get_time += 1; + user_cabi.cpu_period.tv_nsec = tick2nanosec(&get_time); +#ifdef DEBUG_CABI + printk("cabi_create: cpu_period changes into the minimum value (%ldns) of this system.\n", + user_cabi.cpu_period.tv_nsec); +#endif + } + } + + if (time_sec > period_sec) { + return CABI_EINVAL; + } else if (time_sec == period_sec) { + if (time_nsec > period_nsec) { + return CABI_EINVAL; + } + } + + if ((cabi = search_cabi(cabi_id)) == NULL) { + return CABI_ENOEXIST; + } else { + if (user_cabi.cabi_param.bind_proc_type != + cabi->cabi_param.bind_proc_type) + return CABI_EINVAL; + } + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.cabi_param.bind_proc_type == BIND_IDLE_PROC) { + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) == NULL) { + return CABI_EINVAL; + } + if (user_cabi.cabi_param.term_act != CABI_TERM_SIGNAL) { + return CABI_EINVAL; + } + } + + memcpy (&c, &user_cabi.cpu_time, sizeof (struct timespec)); + memcpy (&t, &user_cabi.cpu_period, sizeof (struct timespec)); + memcpy (&p, &user_cabi.cabi_param, sizeof (struct cabi_param)); + + return cabi_account_set(cabi_id, &c, &t, &p); +} + + +asmlinkage int +sys_cabi_account_destroy(unsigned long cabi_id) +{ + /* permission check */ + if (current->euid) { + printk("cabi_destroy: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + if (cabi_id <= 0) + return CABI_EINVAL; /* invalid argument */ + + return cabi_account_destroy(cabi_id); +} + +asmlinkage int +sys_cabi_account_bind_pid(unsigned long cabi_id, pid_t pid) +{ + struct task_struct *tsk; + cabi_account_t cabi; + + /* permission check */ + if (current->euid) { + printk("cabi_bind_pid: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* parameter check */ + if (cabi_id == 0) { + printk("account_attach_process: invalid cabi_id(%d)\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } + + if (pid < 0) { + printk("account_attach_process: invalid pid(%d)\n", (int) pid); + return CABI_EINVAL; /* invalid argument */ + } + if ((cabi = search_cabi(cabi_id)) == NULL) { +#ifdef DEBUG_CABI + printk("cabi_bind_pid: cabi_id(%d) not found.\n", cabi_id); +#endif + return CABI_ENOEXIST; + } else { + if (cabi->cabi_param.term_act == CABI_TERM_NONE) + return CABI_EINVAL; + } + + /* find overload cabi address. */ + if (cabi_id == OVERLOAD_CABI_ID) { + if (pid != IDLE_PROCESS) { + printk("account_bind_pid : overload AO can bind only idol process. pid(%d)\n", pid); + return CABI_EINVAL; + } + if (!(tsk = __cabi_find_idle_process(pid))) { + printk("account_bind_pid : idle (%d) failed.\n", + (int) pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } else { + printk("idle proces(%d) (0x%x) attched.\n", + tsk->pid, (int) tsk); + } + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + printk("account_bind_pid : invalid pid(%d)\n", + (int) pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + if (TASK_ACCOUNT(tsk)) { + printk("account_attach_process: account already " + "attached to this process. pid(%d) cabi(0x%x)\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); + + printk("cabi_account_bind_pid : cabi_id (1) %d, (2) %d\n", + (int) cabi_id, (int) TASK_ACCOUNT(tsk)->cabi_id); + + if (cabi_id == TASK_ACCOUNT(tsk)->cabi_id) { + /* PID is already registered into AO. */ + return CABI_EREGIST; + } else { + /* PID is registered into another AO. */ + return CABI_ENOAVLE; + } + } +#ifdef DEBUG_CABI + else { + printk("attach pid(%d) cabi(0x%x).\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); + + } +#endif + return cabi_account_attach(cabi_id, tsk); +} + +asmlinkage int +sys_cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid) +{ + cabi_account_t cabi; + struct rglist *rg, *tmp; + struct list_head *reg_list; + struct task_struct *tsk; + int i, j, ret; + int already_registered, shouldbe_registered, group_member, rglist_count; + + /* permission check */ + if (current->euid) { + printk("cabi_bind_pgid: Permission denied. EUID [%d], UID [%d].\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + /* if pgid is 0, error return */ + if (pgid == 0) { + printk("cabi_bind_pgid: Can not set 0 as pgid.\n"); + return CABI_EINVAL; + } + + if ((cabi = search_cabi(cabi_id)) == NULL) { +#ifdef DEBUG_CABI + printk("cabi_bind_pgid: cabi_id(%d) not found.\n", cabi_id); +#endif + return CABI_ENOEXIST; + } else { + if (cabi->cabi_param.term_act == CABI_TERM_NONE) + return CABI_EINVAL; + } + + already_registered = shouldbe_registered = + group_member = rglist_count = 0; + + INIT_LIST_HEAD(&rglist_head); + + if (cabi_id == 0) { + printk("account_bind_pgid : invalid cabi_id(%d)\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } else if (cabi_id == OVERLOAD_CABI_ID) { + printk("account_bind_pgid : cabi_id(%d) is only overload.\n", + (int) cabi_id); + return CABI_EINVAL; /* invalid argument */ + } + + /* pigid check */ + if (pgid < 0) { + printk("account_bind_pgid: invalid pgid(%d)\n", (int) pgid); + return CABI_EINVAL; /* invalid argument */ + } + + /* current(caller) check */ + if (TASK_ACCOUNT(current)) { + cabi = TASK_ACCOUNT(current); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + /* If the caller was already binded to other AO, we + * return error. */ + return CABI_ENOAVLE; + } + } else { + /* + * If the caller process has not bind any AO, we shoud + * bind it to the requested AO. But we will not do + * anything here, because for_each_task() routine picks + * up a process as a member of the target group process. + */ + } + + /* + * If the process which is belong to the same group should be + * bind the requested AO. + */ + read_lock(&tasklist_lock); + for_each_task(tsk) { + if (tsk->pgrp == pgid) { + group_member++; +#ifdef DEBUG_CABI + printk("bind_pgid: tsk->pgid %d group_member %d\n", + tsk->pgrp, group_member); +#endif + /* + * The process which has the right pgid was found. + * Next, we shoud check if this process has been + * already bind to other cabi, if so, error return. + */ + if (TASK_ACCOUNT(tsk)) { +#ifdef DEBUG_CABI + printk("bind_pgid: this account already " + "attached to this process. " + " pid(%d) cabi(0x%x)\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); +#endif + /* + * If the process has been registered + * the requested cabi, count up, else + * error return. + */ + cabi = TASK_ACCOUNT(tsk); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + for (i = 0; i < shouldbe_registered; i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + free(rg); + } + read_unlock(&tasklist_lock); + return CABI_ENOAVLE; + } + } else { + /* If the process has not been registered yet, + * we should bind it. But here, we only + * registerd the list. + */ + if((rg = malloc(sizeof (struct rglist))) == NULL) { + for (i = 0; i < shouldbe_registered; i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + free(rg); + } + read_unlock(&tasklist_lock); + return CABI_ENOMEM; + } + bzero(rg, sizeof (struct rglist)); + INIT_LIST_HEAD(&rg->rg_link); + + rg->pid = tsk->pid; + rg->tsk = tsk; + + list_add(&rg->rg_link, &rglist_head); + rglist_count++; + shouldbe_registered++; + } + } + } + read_unlock(&tasklist_lock); + + if (group_member == 0) { + return CABI_EPGNOEXIST; + } else if (group_member == already_registered) { + return CABI_SUCCESS; + } else { + /* regist processes */ + reg_list = &rglist_head; + for (i = 0; i < shouldbe_registered + 1; i++) { + if (reg_list == &rglist_head) { + reg_list = reg_list->next; + } else { + tmp = list_entry(reg_list, struct rglist, + rg_link); +#ifdef DEBUG_CABI + printk("rglist: pid[%d] 0x%x\n", + (int) tmp->pid, (int) tmp->tsk); +#endif + if ((ret = cabi_account_attach(cabi_id, tmp->tsk)) + != CABI_SUCCESS) { + for (j = 0; j < (shouldbe_registered + 1); j++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) + break; + rg = list_entry(reg_list, struct rglist, + rg_link); + list_del(&rg->rg_link); + if (j < (i - 1)) + cabi_account_detach(rg->tsk); + free(rg); + } +#ifdef DEBUG_CABI + printk + ("count: %d bind_pgid attach error : %d\n", + i, ret); +#endif + return ret; + } + reg_list = reg_list->next; + } + } + for (i = 0; i < (shouldbe_registered + 1); i++) { + reg_list = (&rglist_head)->next; + if (reg_list == &rglist_head) { + break; + } + rg = list_entry(reg_list, struct rglist, rg_link); + list_del(&rg->rg_link); + free(rg); + } + } + return CABI_SUCCESS; +} + +asmlinkage int +sys_cabi_account_unbind(pid_t pid) +{ + struct task_struct *tsk; + + /* permission check */ + if (current->euid) { + printk("cabi_unbind: Permission denied. EUID [%d], UID [%d]\n", + current->euid, current->uid); + return CABI_EACCESS; + } + + if (pid < 0) { + printk("account_attach_process: invalid pid(%d)\n", (int) pid); + return CABI_EINVAL; /* Invalid argument */ + } + + /* find overload cabi address. */ + if (pid == IDLE_PROCESS) { + printk("cabi_account_unbind: overload pid %d\n", pid); + if (!(tsk = __cabi_find_idle_process(pid))) { + printk("account_unbind: idle (%d) failed.\n", pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } else { + printk("unbind: idle task(%d) (0x%x)\n", + tsk->pid, (int) tsk); + } + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + printk("cabi_account_unbind: invalid pid(%d)\n", pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + if (!TASK_ACCOUNT(tsk)) { + printk("account_unbind: no account attached to " + "this process. pid(%d)\n", tsk->pid); + return CABI_ENOBIND; + } + + return cabi_account_detach(tsk); +} + +#ifdef CONFIG_PROC_FS +int +cabi_account_read_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + cpu_capacity_t ave, cur, prv; + + cur = CAPACITY_OF(cabi->cpu_period_used_ticks, cabi->cpu_period_ticks); + prv = + CAPACITY_OF(cabi->cpu_period_prev_used_ticks, + cabi->cpu_period_ticks); + + if (cabi->cpu_average.total_count) { + ave = + cabi->cpu_average.total_utils / + cabi->cpu_average.total_count; + } else { + ave = cur; + } + + /* 1st line: utilization statistics + * reseved, previous, average, max, min */ + p += sprintf(p, "%lu.%02lu %lu.%02lu %lu.%02lu %lu.%02lu %lu.%02lu\n", + CAPACITY_INT(cabi->cpu_capacity), + CAPACITY_FRAC(cabi->cpu_capacity), + CAPACITY_INT(prv), CAPACITY_FRAC(prv), + CAPACITY_INT(ave), CAPACITY_FRAC(ave), + CAPACITY_INT(cabi->cpu_max_utilization), + CAPACITY_FRAC(cabi->cpu_max_utilization), + CAPACITY_INT(cabi->cpu_min_utilization), + CAPACITY_FRAC(cabi->cpu_min_utilization)); + + /* 2nd line: current CPU usage + * used available requested */ + p += sprintf(p, "%lu %lu %lu\n", + TICK2USEC(&cabi->cpu_period_used_ticks), + TICK2USEC(&cabi->cpu_period_available_ticks), + TICK2USEC(&cabi->cpu_time_ticks)); + /* 3rd line: count of replenishment */ + p += sprintf(p, "%lu\n", cabi->cpu_average.total_count); + + /* 4th line: account object id */ + p += sprintf(p, "%lu\n", cabi->cabi_id); + + return (p - buf); +} + +int +cabi_account_read_bindpid_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = list_entry(proc_list, struct rs_proc_list, + rs_proc_list); + p += sprintf(p, "%d\n", rs_proc->rs_proc_pid); + /* next element */ + proc_list = proc_list->next; + } + + return (p - buf); +} + +int +cabi_account_status_proc(char *buf) +{ + char *p = buf; + + /* cabi ticks per second, CPU capacity taken for accounts */ + p += sprintf(p, "%lu\n", + (unsigned long) cabi_cpu_ticks_per_second); + + return (p - buf); +} + +int +cabi_account_base_status_proc(char *buf) +{ + char *p = buf; + + p += sprintf(p, "%lu\n", + (unsigned long) cabi_cpu_ticks_per_second); + + return (p - buf); + +} +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_init.c linux-2.4.20-cabi/drivers/cabi/cabi_init.c --- linux-2.4.20/drivers/cabi/cabi_init.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_init.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,148 @@ + /* + * linux/drivers/cabi/cabi_init.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +extern void cabi_account_init(void); +extern void cabi_proc_init(void); + +spinlock_t cabi_lock; +cpu_tick_data_t cabi_cpu_ticks_per_second; +cpu_tick_data_t cabi_cpu_ticks_per_jiffy; +cpu_tick_data_t cabi_timer_adjust; + +#ifdef CONFIG_X86 +void +cabi_cpu_calibration_i386(void) +{ + cpu_tick_data_t begin, end, err; + unsigned long first_jiffies; + int i = 5; + + printk("cabi_cpu_calibration: Calibrating cpu "); + + cabi_rdticks(&begin); + cabi_rdticks(&end); + err = end - begin; + + /* wait for "start of" clock tick */ + first_jiffies = jiffies; + while (first_jiffies == jiffies) { + /* nothing */ + } + cabi_rdticks(&begin); + while (i-- > 0) { + first_jiffies = jiffies; + printk("."); + while (jiffies - first_jiffies < HZ) { + /* nothing */ + } + } + cabi_rdticks(&end); + /* */ + cabi_cpu_ticks_per_second = (end - begin - err) / 5; + { + cpu_tick_data_t t; + t = CABI_NANOSECS_PER_JIFFY; + nanosec2tick(&t, &cabi_cpu_ticks_per_jiffy); + } + /* */ + + printk(" %lu cycles per second.\n", + (unsigned long) cabi_cpu_ticks_per_second); +} +#else /* #ifdef CONFIG_X86 */ +void +cabi_cpu_calibration(void) +{ + printk("cabi initialize...\n"); + cabi_cpu_ticks_per_second = CABI_CLOCK; + { + cpu_tick_data_t t; + t = CABI_NANOSECS_PER_JIFFY; + nanosec2tick(&t, &cabi_cpu_ticks_per_jiffy); + } +} +#endif /* #ifdef CONFIG_X86 */ + +void +cabi_init(void) +{ + spin_lock_init(&cabi_lock); + cabi_account_init(); +#ifdef CONFIG_X86 + cabi_cpu_calibration_i386(); +#else + cabi_cpu_calibration(); +#endif /* #ifdef CONFIG_X86 */ + +#ifdef CONFIG_PROC_FS + cabi_proc_init(); +#endif +} diff -Nru linux-2.4.20/drivers/cabi/cabi_isr.c linux-2.4.20-cabi/drivers/cabi/cabi_isr.c --- linux-2.4.20/drivers/cabi/cabi_isr.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_isr.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,280 @@ +/* + * linux/drivers/cabi/cabi_isr.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include + +#ifdef DEBUG_CABI +#ifdef MONTAVISTA_LINUX +#include +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS +#include +#endif +#undef DEBUG_CABI_ISR +#endif /*DEBUG_CABI */ + +extern cabi_account_t cabi_current_account; +extern cabi_account_t cabi_current_overload_account; +/* + * Hooks + */ +int (*cabi_ret_with_reschedule_hook) (void); + +/* + * For "cabi_ret_with_reschedule_hook", cabi_ret_with_reschedule is called when + * a process exits from the kernel after processing a system call. + */ +asmlinkage int +cabi_ret_with_reschedule(void) +{ + cabi_account_t cabi; + +#ifdef DEBUG_CABI +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); +#endif +#endif + if ((cabi = cabi_current_overload_account)) { + if (cabi_account_overload(cabi)) { + if(!cabi->signal_block) { + cabi_send_signal(cabi, + CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + if (cabi->signal_block) + cabi->term_act_status = CABI_SIGNALAFT; + +#ifdef DEBUG_CABI + printk + ("ret_with: overload pid(%d), cabi->cpu_state(%x)\n", + current->pid, cabi->cpu_state); +#endif + } + } + } + + if ((cabi = cabi_current_account)) { + if ((cabi_account_depleted(cabi))) { + + switch (cabi->cabi_param.term_act) { + case CABI_TERM_BLOCK: + +#if defined(DEBUG_CABI_ISR) || defined(DEBUG_CABI_ENFORCE) +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk + ("cabi_ret_with_reschedule: depleted cabi(0x%x) " + "pid(%d) current(%lu, %lu)\n", (int) cabi, + current->pid, now.jiffies, + (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk + ("cabi_ret_with_reschedule: depleted cabi(0x%x) " + "pid(%d) current(%lu, %lu)\n", (int) cabi, + current->pid, jiffies, + (u_long) sub_jiffie()); +#else + printk + ("cabi_ret_with_reschedule: depleted cabi(v0x%x) " + "pid(%d) current(%lu)\n", (int) cabi, + current->pid, jiffies); +#endif +#endif /* DEBUG_CABI_ENFORCE */ + + if (!cabi->term_act_status) { + cabi->term_act_status + = CABI_BLOCKED; + cabi->block_count++; + } + + __sti(); + cabi_account_sleep_on(cabi); +#ifdef DEBUG_CABI + printk("cabi_account_sleep_on\n"); +#endif + return 1; + break; + + case CABI_TERM_SIGNAL: +#ifdef DEBUG_CABI + printk + ("signal: id(%d), current(0x%x,0x%x)\n", + (int) cabi_current_account->cabi_id, + (int) cabi, + (int) cabi_current_account); +#endif + if (cabi_is_overload_account(cabi)) { +#ifdef DEBUG_CABI + printk + ("cabi is overload, return.\n"); +#endif + return 1; + } + if (!cabi->signal_block) { + cabi_send_signal(cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + + /* if signal flag is on, signal was sent. */ + if (cabi->signal_block) + cabi->term_act_status = CABI_SIGNALAFT; + + } else { +#ifdef DEBUG_CABI + printk + ("Already sent signal. %d\n", + cabi->signal_block); +#endif + } + break; + case CABI_TERM_UNKNOWN: + case CABI_TERM_NONE: + cabi_current_account = NULL_ACCOUNT; + +#ifdef DEBUG_CABI + printk("cabi_ret_with_reschedule : " + "null account : term_act(%d)\n", + cabi->cabi_param.term_act); +#endif + break; + default: + cabi_current_account = NULL_ACCOUNT; +#ifdef DEBUG_CABI + printk("cabi_ret_with_reschedule: cabi(0x%x)" + "term_act(%d)\n", + (int) cabi, cabi->cabi_param.term_act); +#endif + } + } + } + return 0; +} + +void +cabi_enable_isr(void) +{ + unsigned long flags; + + if (cabi_ret_with_reschedule_hook == cabi_ret_with_reschedule) + return; + + cabi_spin_lock(flags); + { + /* install hooks */ + cabi_ret_with_reschedule_hook = cabi_ret_with_reschedule; + /* start Rk timer */ + cabi_timer_start(); + } + cabi_spin_unlock(flags); +#ifdef DEBUG_CABI + printk("cabi_enable_isr: cabi kernel in/out hook enabled.\n"); +#endif +} + +void +cabi_disable_isr(void) +{ + unsigned long flags; + + if (cabi_ret_with_reschedule_hook == (void *) 0) + return; + + cabi_spin_lock(flags); + { + /* remove hooks */ + cabi_ret_with_reschedule_hook = (void *) 0; + } + cabi_spin_unlock(flags); +#ifdef DEBUG_CABI + printk("cabi_disable_isr: cabi kernel in/out hook diabled.\n"); +#endif +} + + +#ifdef CONFIG_PROC_FS + +int +cabi_account_read_block_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + + if (cabi->term_act_status == CABI_UNBLOCK || + cabi->term_act_status == CABI_BLOCKED) { + p += sprintf(p, "%d\n%lu\n", cabi->term_act_status, + cabi->block_count); + } else { + p += sprintf(p, "%d\n%lu\n", cabi->term_act_status, + cabi->signal_count); + } + return (p - buf); +} + +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_procfs.c linux-2.4.20-cabi/drivers/cabi/cabi_procfs.c --- linux-2.4.20/drivers/cabi/cabi_procfs.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_procfs.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,235 @@ + /* + * linux/drivers/cabi/cabi_procfs.c - implements the interfaces for procfs. + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +#include +#include +#include + +#include + +#define MAX_LEN 10 + +#ifdef CONFIG_PROC_FS + +/* proc root directory */ +static struct proc_dir_entry *proc_cabi_dir; +/* proc object_id directories */ + +static int +proc_cabi_status_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_proc(cabi, page); +} + +static int +proc_cabi_base_status_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + extern int cabi_account_base_status_proc(char *); + + p += cabi_account_base_status_proc(p); + + return (p - page); +} + +static int +proc_cabi_block_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + +#ifdef DEBUG_CABI + printk("term_act_status %d\n", cabi->term_act_status); +#endif + return cabi_account_read_block_proc(cabi, page); + +} + +static int +proc_cabi_bindpid_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_bindpid_proc (cabi, page); + +} + +static int +proc_cabi_time_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_time_proc(cabi, page); +} + +void __init +cabi_proc_init(void) +{ + struct proc_dir_entry *proc_cabi_status; + + /* proc directory entry */ + proc_cabi_dir = create_proc_entry("cabi", S_IFDIR, 0); + + if (!proc_cabi_dir) { + printk("Can't create /proc/cabi\n"); + return; + } + + proc_cabi_status = create_proc_entry("cabi_status", S_IFREG | S_IRUGO, + proc_cabi_dir); + proc_cabi_status->read_proc = proc_cabi_base_status_read; +} + + +struct cabi_entry_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} CABI_PROC_ENTRY[] = { + { "status", proc_cabi_status_read}, + { "term_act", proc_cabi_block_read}, + { "bind_pid", proc_cabi_bindpid_read}, + { "time_set", proc_cabi_time_read}, +}; + +int +cabi_register_proc_account(cabi_account_t cabi) +{ + int i; + struct proc_dir_entry *entry; + unsigned char string[MAX_LEN]; + + sprintf(string, "%d", (int) cabi->cabi_id); + + if (!proc_cabi_dir) + return CABI_ERROR; + + cabi->cpu_proc_entry = proc_mkdir (string, proc_cabi_dir); + + if (!(cabi->cpu_proc_entry)) { + printk("Can't create /proc/cabi/%d\n", (int)cabi->cabi_id); + return CABI_ERROR; + } + for (i = 0; i < CABI_PROC_ENTRIES; i++) { + entry = create_proc_entry (CABI_PROC_ENTRY[i].name, + S_IFREG|S_IRUGO, cabi->cpu_proc_entry); + + if (!entry) { + printk("Can't create /proc/cabi/%d/%s\n", + (int) cabi->cabi_id, CABI_PROC_ENTRY[i].name); + return CABI_ERROR; + } + entry->nlink = 1; + entry->data = cabi; + entry->read_proc = *CABI_PROC_ENTRY[i].f; + } + + return CABI_SUCCESS; + +} + + +int +cabi_proc_account_create(cabi_account_t cabi) +{ + +#ifdef DEBUG_CABI + printk("cabi_proc_account_create: cabi(0x%x) cabi_id (%d) \n", + (int) cabi, (int) cabi->cabi_id); +#endif + return cabi_register_proc_account(cabi); + +} + +int +cabi_proc_account_destroy(cabi_account_t cabi) +{ + int i; + char buf[16]; + +#ifdef DEBUG_CABI + printk("cabi_proc_account_destroy: cabi(%d)", (int) cabi->cabi_id); +#endif + + if (!proc_cabi_dir) + return CABI_ERROR; + + for (i = 0; i < CABI_PROC_ENTRIES; i++) { + remove_proc_entry (CABI_PROC_ENTRY[i].name, + cabi->cpu_proc_entry); + } + sprintf(buf, "%d", (int) cabi->cabi_id); + remove_proc_entry(buf, proc_cabi_dir); + + return CABI_SUCCESS; + +} + +#endif /* CONFIG_PROC_FS */ diff -Nru linux-2.4.20/drivers/cabi/cabi_sched.c linux-2.4.20-cabi/drivers/cabi/cabi_sched.c --- linux-2.4.20/drivers/cabi/cabi_sched.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_sched.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,163 @@ + /* + * linux/drivers/cabi/cabi_sched.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include + +#ifdef MONTAVISTA_LINUX +#include +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS +#include +#endif + /**/ +/* #undef DEBUG_CABI_SCHED */ + /**/ extern cabi_account_t cabi_current_account; + +void (*cabi_schedule_hook) (struct task_struct *, struct task_struct *); + +void +cabi_schedule_cpu(struct task_struct *prev, struct task_struct *next) +{ + cpu_tick_data_t now; + cabi_account_t prev_cabi = TASK_ACCOUNT(prev); + cabi_account_t next_cabi = TASK_ACCOUNT(next); + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct pnow; + posix_get_now(&pnow); +#endif + +#ifdef DEBUG_CABI_SCHED + if (prev_cabi || next_cabi) { + printk + ("cabi_schedule_cpu: pid(%d) cabi(0x%x) -> pid(%d) cabi(0x%x)\n", + prev->pid, (int) prev_cabi, next->pid, (int) next_cabi); + } +#endif + if (prev_cabi != next_cabi) { + /* if there is a current cabi, stop it */ + if (prev_cabi == cabi_current_account) { + if (cabi_current_account) { + cabi_rdticks(&now); + cabi_stop_account(cabi_current_account, &now); + } + } + + /* if there is a cabi for next, start it */ + if ((cabi_current_account = next_cabi)) { +#ifdef DEBUG_CABI +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu, %lu) next_cabi_id[%d]\n", + (int) next_cabi, pnow.jiffies, + (u_long) pnow.sub_jiffie, + (int) next_cabi->cabi_id); + +#elif CONFIG_HIGH_RES_TIMERS + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu, %lu) next_cabi_id[%d]\n", + (int) next_cabi, jiffies, (u_long) sub_jiffie(), + (int) next_cabi->cabi_id); +#else + printk("cabi_schedule_cpu: cabi(0x%x) depleted. " + "current(%lu) next_cabi_id[%d] \n", + (int) next_cabi, jiffies, + (int) next_cabi->cabi_id); +#endif +#endif + cabi_start_account(next_cabi); + } + } + cabi_current_account = next_cabi; +} + +void +cabi_enable_schedule_cpu(void) +{ + if (!cabi_schedule_hook) { + cabi_schedule_hook = cabi_schedule_cpu; +#ifdef DEBUG_CABI + printk + ("cabi_enable_schedule_cpu: cabi_schedule_hook enabled\n"); +#endif + } +} + +void +cabi_disable_schedule_cpu(void) +{ + if (cabi_schedule_hook) { + cabi_schedule_hook = (void *) 0; +#ifdef DEBUG_CABI + printk + ("cabi_disable_schedule_cpu: cabi_schedule_hook disabled\n"); +#endif + + } +} diff -Nru linux-2.4.20/drivers/cabi/cabi_signal.c linux-2.4.20-cabi/drivers/cabi/cabi_signal.c --- linux-2.4.20/drivers/cabi/cabi_signal.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_signal.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,128 @@ + /* + * linux/drivers/cabi/cabi_signal.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +int +cabi_send_signal(cabi_account_t cabi, int pid, int sig) +{ + + int error; + struct siginfo info; + struct task_struct *tsk; + + /* Set the siginfo */ + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_KERNEL; + info.si_pid = 0; + info.si_uid = 0; + + if (sig <= 0) + return -EINVAL; + + /* This is only valid for normal process(not idle process). */ + if (pid <= 0) + return -EINVAL; + + error = -ESRCH; + + /* search process by pid */ + if (!(tsk = __cabi_find_process_by_pid(pid))) { +#ifdef DEBUG_CABI + printk("cabi_send_signal: invalid pid (%d).\n", pid); + printk("Cabi did not send signal, not exist received process. (%d)\n", pid); +#endif + return error; + } else { +#ifdef DEBUG_CABI + printk("cabi_send_signal: pid %d sig %d \n", pid, sig); + printk("[signal] pid %d status %d\n", + (int) tsk->pid, (int)tsk->state); + printk("signal_struct: count %d\n", + (int)tsk->sig->count.counter); +#endif + error = send_sig_info(sig, &info, tsk); + + if (error<0) { +#ifdef DEBUG_CABI + printk("Could not send %d signal\n", sig); +#endif + } else { +#ifdef DEBUG_CABI + printk("Signal %d was sent.\n", sig); +#endif + cabi->signal_block = SIGNAL_ON; + cabi->signal_count++; + } + + } + return error; + +} diff -Nru linux-2.4.20/drivers/cabi/cabi_timer.c linux-2.4.20-cabi/drivers/cabi/cabi_timer.c --- linux-2.4.20/drivers/cabi/cabi_timer.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/cabi_timer.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,455 @@ + /* + * linux/drivers/cabi/cabi_timer.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include + +#ifdef MONTAVISTA_LINUX +#include +#include +extern struct k_clock posix_clocks[MAX_CLOCKS]; + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + +#include +#include +extern int nsec_to_arch_cycle(unsigned long nsec); + +int +tstojiffie(struct timespec *tp, int res, unsigned long *jiff) +{ + unsigned long sec = tp->tv_sec; + long nsec = tp->tv_nsec + res - 1; + + /* + * A note on jiffy overflow: It is possible for the system to + * have been up long enough for the jiffies quanity to overflow. + * In order for correct timer evaluations we require that the + * specified time be somewhere between now and now + (max + * unsigned int/2). Times beyond this will be truncated back to + * this value. This is done in the absolute adjustment code, + * below. Here it is enough to just discard the high order + * bits. + */ + *jiff = HZ * sec; + /* + * Do the res thing. (Don't forget the add in the declaration of nsec) + */ + nsec -= nsec % res; + /* + * Split to jiffie and sub jiffie + */ + *jiff += nsec / (NSEC_PER_SEC / HZ); + /* + * We trust that the optimizer will use the remainder from the + * above div in the following operation as long as they are close. + */ + + return (nsec_to_arch_cycle(nsec % (NSEC_PER_SEC / HZ))); +} + +#else +__inline__ void +tstojiffie(struct timespec *tp, unsigned long *jiff) +{ + *jiff = HZ * tp->tv_sec; + *jiff += (tp->tv_nsec + (NANOSEC / HZ)) / (NANOSEC / HZ); +} +#endif /* CONFIG_HRES_TIMERS & MONTAVISTA_LINUX */ + +#else /* NOT MONTAVISTA_LINUX */ + +#ifdef CONFIG_HIGH_RES_TIMERS +#include /* for high-resolution timer */ + int tstojiffie(struct timespec *tp, int res, unsigned long *jiff); +#else +__inline__ void +cabi_tstojiffie(struct timespec *tp, unsigned long *jiff) +{ + *jiff = HZ * tp->tv_sec; + *jiff += (tp->tv_nsec + (NANOSEC / HZ)) / (NANOSEC / HZ); +} +#endif /* CONFIG_HRES_TIMERS & !MONTAVISTA_LINUX */ +#endif /* MONTAVISTA_LINUX */ + +#ifdef CONFIG_HIGH_RES_TIMERS +long enf_hrt_sub_expires; +long rep_hrt_sub_expires; +#else +unsigned long enf_cabi_expires; +unsigned long rep_cabi_expires; +#endif + +#define SUBJIFF2NANOSEC 1000 +#define JIFF2NANOSEC 10000000 +#define NANOSEC_PER_SECOND 1000000000 +#define MICROSEC_PER_SECOND 1000000 +#define JIFF2MILISEC 10 +#define MICROSEC2NANOSEC 1000 +#define SEC2MILISEC 1000 + +extern cabi_account_t cabi_current_account; +extern int init_timer_flag; + +/* + * cabi_replenish_timer_process(cabi_timer_t tmr) + */ +void +cabi_replenish_timer_process(cabi_account_t cabi) +{ + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + struct timespec period; + +#ifdef CONFIG_HIGH_RES_TIMERS + int res = posix_clocks[CLOCK_REALTIME_HR].res; +#endif + +#ifdef DEBUG_CABI_REPLENISH_TIMER + printk + ("cabi_replenish_timer_process: current jiffies(%lu) cabi_state(%x)\n", + jiffies, cabi->cpu_state); +#endif + /* replenish it, and set timer expiration `ticks' later */ + cabi_account_replenish(cabi, &period); + +#if CONFIG_HIGH_RES_TIMERS + tmr->sub_expires = rep_hrt_sub_expires = + tstojiffie(&period, res, &tmr->expires); +#else + cabi_tstojiffie(&period, &tmr->expires); + rep_cabi_expires = tmr->expires; + +#endif + tmr->expires += jiffies; + +#ifdef DEBUG_CABI_REPLENISH_TIMER +#ifdef CONFIG_HIGH_RES_TIMERS + printk + ("cabi_replenish_hres_timer_process: set next timer for cabi(0x%x) (%lu sec,%lu nsec) (%lu,%lu,%lu)\n", + (int) cabi, period.tv_sec, period.tv_nsec, tmr->expires, + tmr->sub_expires, jiffies); +#else + printk + ("cabi_replenish_timer_process: set next timer for cabi(0x%x) (%lu sec,%lu nsec) (%lu)\n", + (int) cabi, period.tv_sec, period.tv_nsec, tmr->expires); +#endif +#endif + /* Enqueue the timer */ + add_timer(tmr); +} + +/* + * cabi_replenish_timer_create(): + * Create a timer to replenish a account, add it to the queue. + * Set a linux timer if necessary. + */ +void +cabi_replenish_timer_init(cabi_account_t cabi, cpu_tick_t ticks) +{ + + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + /* initialize a (linux) timer for replenishment */ + init_timer(tmr); + + /* Always start from the next jiffy */ + tmr->expires = jiffies + 1; + tmr->function = (void (*)(unsigned long)) cabi_replenish_timer_process; + tmr->data = (unsigned long) cabi; + +#ifdef DEBUG_CABI_REPLENISH_TIMER +#ifdef CONFIG_HIGH_RES_TIMERS + printk + ("cabi_replenish_timer_init(replenish_hres) set next timer for cabi(0x%x) (%lu,%lu)\n", + (int) cabi, tmr->expires, tmr->sub_expires); +#else + printk("cabi_replenish_timer_process: set next timer for cabi(0x%x) " + "(%lu)\n", (int) cabi, tmr->expires); +#endif +#endif + /* adjust the count of replenishment */ + cabi->cpu_average.total_count--; + + /* set init_timer flag */ + init_timer_flag = 0; + + /* Enqueue the timer */ + add_timer(tmr); +} + +void +cabi_replenish_timer_cancel(cabi_account_t cabi) +{ + int ret; + struct timer_list *tmr = &cabi->cpu_replenish_tmr; + + ret = del_timer_sync(tmr); +#ifdef DEBUG_CABI + if(ret <= 0) + printk("Can't delete replenish timer %d.\n", ret); + else + printk("delete replenish_timer %d.\n", ret); +#endif +} + + +/* + * Enforcement timer management + * + * cabi_start_account(cabi) + * -> cabi_timer_set_enforce_timer(cabi, ticks_expired); + * + * cabi_stop_account(cabi) + * -> cabi_timer_cancel_enforce_timer(cabi); + * + * "cabi_current_resource_set != 0" --> accounting is on + * "cabi_current_resource_set == 0" --> accounting is off + * + */ +extern void cabi_enforce_timer_process(cabi_account_t cabi); +static struct timer_list cabi_enforce_timer = { + function:(void (*)(unsigned long)) cabi_enforce_timer_process +}; + +/* called from "cabi->cpu_ops->start_account()" */ +void +cabi_enforce_timer_start(cabi_account_t cabi, cpu_tick_t next_available_ticks) +{ + + struct timer_list *tmr = &cabi_enforce_timer; + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); +#endif + +#ifdef CONFIG_HIGH_RES_TIMERS + int res = posix_clocks[CLOCK_REALTIME_HR].res; +#endif + struct timespec ts; + tick2ts(next_available_ticks, &ts); + +#if CONFIG_HIGH_RES_TIMERS + tmr->sub_expires = enf_hrt_sub_expires = + tstojiffie(&ts, res, &tmr->expires); + +#else + cabi_tstojiffie(&ts, &tmr->expires); + enf_cabi_expires = tmr->expires; +#endif + +#ifdef DEBUG_CABI_ENFORCE_TIMER_START + +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + printk + ("[cabi_enforce_hres_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu,%lu) curent(%lu, %lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, tmr->sub_expires, now.jiffies, + (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk + ("[cabi_enforce_hres_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu,%lu) curent(%lu, %lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, tmr->sub_expires, jiffies, (u_long) sub_jiffie()); +#else + printk + ("[cabi_enforce_timer_start]: cabi(0x%x) (%lu usec) (%lu sec, %lu nsec) " + "(%lu) cuurent(%lu)\n", (int) cabi, + TICK2USEC(next_available_ticks), ts.tv_sec, ts.tv_nsec, + tmr->expires, jiffies); +#endif +#endif + tmr->expires += jiffies; + tmr->data = (unsigned long) cabi; + + /* Enqueue the timer */ + mod_timer(tmr, tmr->expires); + return; +} + +/* + * Cancel enforce_timer and set timer to next jiffy + */ +void +cabi_enforce_timer_cancel(void) +{ + int ret; + struct timer_list *tmr = &cabi_enforce_timer; + + ret = del_timer_sync(tmr); +#ifdef DEBUG_CABI + if (ret <= 0) + printk("Can't delete enforce timer %d.\n", ret); + else + printk("delete enforce timer %d.\n", ret); +#endif + +} + +void +cabi_enforce_timer_init(struct timer_list *cabi_enforce_timer) +{ + init_timer(cabi_enforce_timer); +} + +/* + * Process enforce timer expiration. + */ +void +cabi_enforce_timer_process(cabi_account_t cabi) +{ + +#ifdef DEBUG_CABI_ENFORCE_TIMER +#if (CONFIG_HIGH_RES_TIMERS & MONTAVISTA_LINUX) + struct now_struct now; + posix_get_now(&now); + printk("cabi_enforce_hres_timer_process: current jiffies(%lu, %lu)\n", + now.jiffies, (u_long) now.sub_jiffie); + +#elif CONFIG_HIGH_RES_TIMERS + printk("cabi_enforce_hres_timer_process: current jiffies(%lu, %lu)\n", + jiffies, (u_long) sub_jiffie()); +#else + printk("cabi_enforce_timer_process: current jiffies(%lu)\n", jiffies); +#endif +#endif + + /* make sure if cabi corresponds to the current cabi */ + if (cabi_current_account == cabi) { + cabi_account_enforce(cabi_current_account); + } +} + +void +cabi_timer_start(void) +{ + init_timer(&cabi_enforce_timer); +} + +int +cabi_account_read_time_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + unsigned long cjiff, cs_jiff, cn_jiff, tjiff, ts_jiff, tn_jiff; + + /* 1st : setting parameter for timespec struct */ + p += sprintf(p, "%lu %02lu %lu %02lu\n", + cabi->cpu_time.tv_sec, cabi->cpu_time.tv_nsec, + cabi->cpu_period.tv_sec,cabi->cpu_period.tv_nsec); + +#ifdef CONFIG_HIGH_RES_TIMERS + p += sprintf(p, "%d\n", 1); + p += sprintf(p, "%02lu %02lu\n", + enf_hrt_sub_expires, rep_hrt_sub_expires); + +#else + cjiff = HZ * cabi->cpu_time.tv_sec; + cjiff += (cabi->cpu_time.tv_nsec + (NANOSEC_PER_SECOND/HZ)) + / (NANOSEC_PER_SECOND / HZ); + cjiff += (cabi->cpu_time.tv_nsec) / (NANOSEC_PER_SECOND / HZ); + /* second */ + cs_jiff = cjiff * JIFF2MILISEC / SEC2MILISEC; + /* nanosec */ + cn_jiff = cjiff * JIFF2MILISEC % MICROSEC2NANOSEC; + cn_jiff *= MICROSEC_PER_SECOND; + +#ifdef DEBUG_CABI + printk("enforce_time : %lu jiffies %lu sec, %lu nsec", + cjiff, cs_jiff, cn_jiff); +#endif + + tjiff = HZ * cabi->cpu_period.tv_sec; + tjiff += (cabi->cpu_period.tv_nsec + (NANOSEC_PER_SECOND/HZ)) + / (NANOSEC_PER_SECOND / HZ ); + tjiff += (cabi->cpu_period.tv_nsec) / (NANOSEC_PER_SECOND / HZ); + /* second */ + ts_jiff = tjiff * JIFF2MILISEC / SEC2MILISEC; + /* nanosec */ + tn_jiff = tjiff * JIFF2MILISEC % MICROSEC2NANOSEC; + tn_jiff *= MICROSEC_PER_SECOND; + +#ifdef DEBUG_CABI + printk("replenish_time : %lu jiffies %lu sec, %lu nsec", + tjiff, ts_jiff, tn_jiff); +#endif + p += sprintf(p, "%d\n", 0); + p += sprintf(p, "%lu %02lu %lu %02lu\n", + cs_jiff, cn_jiff, ts_jiff, tn_jiff); + +#endif + + return (p - buf); +} + diff -Nru linux-2.4.20/drivers/cabi/examples/Makefile linux-2.4.20-cabi/drivers/cabi/examples/Makefile --- linux-2.4.20/drivers/cabi/examples/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/Makefile 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,54 @@ +CABIDIR = ../.. +CC = gcc -g +LIBS = -lcabi +CFLAGS = -O2 -Wall +INCLUDES = -I /usr/include + +OBJS = cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get \ + cabi_overload_create cabi_overload_destroy \ + cabi_create_bind cabi_exec_bind \ + cabi_get_bind_pid cabi_get_used_time cabi_get_status \ + +all: cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get cabi_overload_create cabi_overload_destroy cabi_create_bind cabi_exec_bind cabi_get_bind_pid cabi_get_used_time cabi_get_status + +cabi_create: cb_create.c + $(CC) -o cabi_create cb_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_destroy: cb_destroy.c + $(CC) -o cabi_destroy cb_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_bind: cb_bind.c + $(CC) -o cabi_bind cb_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_unbind: cb_unbind.c + $(CC) -o cabi_unbind cb_unbind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_set: cb_set.c + $(CC) -o cabi_set cb_set.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get: cb_get.c + $(CC) -o cabi_get cb_get.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_create: cb_overload_create.c + $(CC) -o cabi_overload_create cb_overload_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_destroy: cb_overload_destroy.c + $(CC) -o cabi_overload_destroy cb_overload_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_create_bind: cb_create_bind.c + $(CC) -o cabi_create_bind cb_create_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_exec_bind: cb_exec_bind.c + $(CC) -o cabi_exec_bind cb_exec_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_bind_pid: cb_get_bind_pid.c + $(CC) -o cabi_get_bind_pid cb_get_bind_pid.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_used_time: cb_get_used_time.c + $(CC) -o cabi_get_used_time cb_get_used_time.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get_status: cb_get_status.c + $(CC) -o cabi_get_status cb_get_status.c $(CFLAGS) $(INCLUDES) $(LIBS) + +clean: + rm -rf $(OBJS) *~ diff -Nru linux-2.4.20/drivers/cabi/examples/cb_bind.c linux-2.4.20-cabi/drivers/cabi/examples/cb_bind.c --- linux-2.4.20/drivers/cabi/examples/cb_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_bind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_bind [object_id] [pid]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [pid] : bind process id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + unsigned long cabi_id; + + if (argc != 3) { + usage(); + return 0; + } + + /* set accounting object id */ + cabi_id = atol (argv[1]); + pid = (pid_t) atoi (argv[2]); + + switch (cabi_id) { + case 0: + printf ("object id is 0.\n"); + return 1; + case 1: + printf ("[object_id]=1 is only for overload."); + return 1; + default: + printf ("cabi bind pid\n"); + break; + } + + // Attach this process to the resource set + if ((ret = cabi_account_bind_pid(cabi_id, pid)) != CABI_SUCCESS) { + printf ("cabi_account_bind_pid() faild.(%d)\n", ret); + } else { + printf ("cabi_account_bind_pid: object_id(%d) pid[%d]\n", + (int)cabi_id, pid); + } + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_create.c linux-2.4.20-cabi/drivers/cabi/examples/cb_create.c --- linux-2.4.20/drivers/cabi/examples/cb_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_create.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,118 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +void usage(void) { + printf ("cabi_create:\n"); + printf (" cabi terminate action [block]:\n"); + printf (" Usage: cabi_create [cpu_time(us)] [cpu_period(us)]\n"); + printf (" cabi terminate action [signal]:\n"); + printf (" Usage: cabi_create [cpu_time(us)] [cpu_period(us)] [pid] [sig] [flag]\n"); + printf ("--------------------------------------------------\n"); + printf (" [cpu_time(us)] : cpu performance time (usec)\n"); + printf (" [cpu_period(us)] : cpu cycle time (usec)\n"); + printf (" [pid] : signal receive pid\n"); + printf (" [sig] : send signal number\n"); + printf (" [flag] : default(current) or else\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + struct cabi_uaccount *ucabi; + long long cpu_time, cpu_period; + int term_act, sig, flag; + pid_t pid; + + /* set accounting object id */ + switch (argc) { + case 3: + term_act = CABI_TERM_BLOCK; + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + pid = 0; + sig = 0; + flag = 0; + break; + case 6: + term_act = CABI_TERM_SIGNAL; + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + pid = atoi (argv[3]); + sig = atoi (argv[4]); + flag = atoi (argv[5]); + break; + default: + usage(); + return 1; + } + printf ("Create CABI object...\n"); + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a user cabi */ + if(!(ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)))) { + printf ("cabi_create: Memory allocation error.\n"); + return 1; + } + + ucabi->cabi_param.term_act = term_act; + ucabi->cabi_param.bind_proc_type = BIND_NORMAL_PROC; + + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + ucabi->cabi_param.cabi_signal.pid = pid; + ucabi->cabi_param.cabi_signal.sig = sig; + ucabi->cabi_param.cabi_signal.flag = flag; + + if ((ret = cabi_account_create (ucabi)) == CABI_SUCCESS) { + printf ("account set create.(%d) object_id [%d]\n", + (int)ucabi->cabi_param.term_act, + (int)ucabi->cabi_id); + } else { + printf ("cabi_account_create failed.(%d)\n", ret); + } + + if (ucabi->cabi_id == 0) { + printf ("cabi_account_create faild on cpu %x\n", (int)ucabi); + free(ucabi); + return 1; + } + + free(ucabi); + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_create_bind.c linux-2.4.20-cabi/drivers/cabi/examples/cb_create_bind.c --- linux-2.4.20/drivers/cabi/examples/cb_create_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_create_bind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,50 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + struct cabi_uaccount *ucabi; + + pid = getpid(); + ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)); + + memset (ucabi, 0x00, sizeof(struct cabi_uaccount)); + /* set scheduling and enforce mode */ + ucabi->cabi_param.term_act = CABI_TERM_BLOCK; + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 1000 * 1000 * 20; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 1000 * 1000 * 100; + + if (!(ret = cabi_create_bind (ucabi, pid))) { + printf("account set create. object_id [%d]\n", + (int)ucabi->cabi_id); + } else { + printf("cabi_account_create failed.\n"); + } + + if (ucabi->cabi_id == 0) { + printf("cabi_account_create faild on cpu %x\n", (int)ucabi); + return 1; + } + + free(ucabi); + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_destroy.c linux-2.4.20-cabi/drivers/cabi/examples/cb_destroy.c --- linux-2.4.20/drivers/cabi/examples/cb_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_destroy.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_destroy [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + unsigned long cabi_id; + + if (argc != 2) { + usage(); + return 0; + } + + /* set the object id */ + cabi_id = atol (argv[1]); + + if ((ret = cabi_account_destroy(cabi_id)) != CABI_SUCCESS) { + printf ("destroy faild.(%d)\n", ret); + } else { + printf ("destroy succeed.\n"); + } + + return 1; + + +} + + diff -Nru linux-2.4.20/drivers/cabi/examples/cb_exec_bind.c linux-2.4.20-cabi/drivers/cabi/examples/cb_exec_bind.c --- linux-2.4.20/drivers/cabi/examples/cb_exec_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_exec_bind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int errno; + +void usage(void) { + printf ("Usage: cabi_exec_bind [object_id] [program...]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [program...] : execute program\n"); +} + +int main (int argc, char *argv[]) +{ + unsigned long cabi_id; + pid_t pid; + int status; + int ret; + + if (argc < 3) { + usage(); + return 0; + } + + cabi_id = atoi (argv[1]); + + if ((pid = fork()) == -1) { + perror("fork()"); + return 1; + } else if (pid > 0) { + if ((ret = cabi_account_bind_pid(cabi_id, pid)) != CABI_SUCCESS) { + printf("exec_bind : cabi_account_bind_pid: faild. (%d)\n", ret); + return 1; + } else { + printf("exec_bind : cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int)cabi_id, pid); + } + waitpid(-1, &status, WNOHANG); + } else { + if (execvp(argv[2], &argv[2]) == -1) { + perror("execv"); + return 1; + } + } + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_get.c linux-2.4.20-cabi/drivers/cabi/examples/cb_get.c --- linux-2.4.20/drivers/cabi/examples/cb_get.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_get.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,79 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_get [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + struct cabi_uaccount *ucabi; + unsigned long cabi_id; + unsigned long long cpu_time, cpu_period; + float cpu_ratio; + int ret; + + if (argc != 2) { + usage(); + return 0; + } + + /* set accounting object id */ + cabi_id = atoi (argv[1]); + + if (cabi_id == 0) { + printf("object id is 0\n"); + return 1; + } + + /* create a user cabi */ + ucabi = (struct cabi_uaccount *) malloc (sizeof(struct cabi_uaccount)); + + if ((ret = cabi_account_get (cabi_id, ucabi)) == CABI_SUCCESS) { + printf("object_id (%d)\n", + (int)ucabi->cabi_id); + } else { + if (ret == CABI_ENOEXIST) { + printf("object id(%ld) not found.\n", cabi_id); + } else { + printf("cabi_account_get failed.(%d)\n", ret); + } + return 1; + } + if (!ucabi) { + printf("cabi_account_get faild on cpu %p\n", ucabi); + return 1; + } + + cpu_time = ucabi->cpu_time.tv_sec * 1000 + ucabi->cpu_time.tv_nsec / 1000000; + cpu_period = ucabi->cpu_period.tv_sec * 1000 + ucabi->cpu_period.tv_nsec / 1000000; + cpu_ratio = (float)cpu_time / (float)cpu_period * 100.0; + + printf ("TERM_ACT (%x)\n", ucabi->cabi_param.term_act); + printf ("CPU_TIME (%lu sec %02lu nsec) /CPU_PERIOD (%lu sec %02lu nsec)\n", + ucabi->cpu_time.tv_sec, + ucabi->cpu_time.tv_nsec, + ucabi->cpu_period.tv_sec, + ucabi->cpu_period.tv_nsec); + printf ("CPU_RATIO (%5.2f %%)\n", cpu_ratio); + + free(ucabi); + + return 0; +} + + diff -Nru linux-2.4.20/drivers/cabi/examples/cb_get_bind_pid.c linux-2.4.20-cabi/drivers/cabi/examples/cb_get_bind_pid.c --- linux-2.4.20/drivers/cabi/examples/cb_get_bind_pid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_get_bind_pid.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,50 @@ +/* + * This is sample program for CABI system. + * get bind pid. + */ + +#include +#include +#include +#include + +extern int cabi_get_bind_pid(unsigned long cabi_id, unsigned int *count, int *pidlist); + +void usage(void) { + printf ("Usage: cabi_get_bind_pid [object_id] [count]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [count] : search binding pid num\n"); +} + +int main (int argc, char *argv[]) +{ + unsigned long cabi_id; + unsigned int count; + int *pidlist; + int i, ret; + + if (argc != 3) { + usage(); + return 0; + } + + cabi_id = atol (argv[1]); + count = atoi (argv[2]); + + pidlist = (int *) malloc (sizeof(int) * count); + + if ((ret = cabi_get_bind_pid(cabi_id, &count, pidlist)) != CABI_SUCCESS) { + printf ("cabi_get_bind_pid: Error (%d)\n", ret); + return 1; + } + + printf("pid count = %d\n", count); + for (i = 0; i < count; i++) { + printf(" pid[%d] = %d\n", i, pidlist[i]); + } + + free (pidlist); + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_get_status.c linux-2.4.20-cabi/drivers/cabi/examples/cb_get_status.c --- linux-2.4.20/drivers/cabi/examples/cb_get_status.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_get_status.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,60 @@ +/* + * This is sample program for CABI system. + * get bind pid. + */ + +#include +#include +#include +#include + +extern int cabi_get_status(unsigned long cabi_id, int *status, unsigned long *count); + +void usage(void) { + printf ("Usage: cabi_get_status [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + unsigned long cabi_id; + unsigned long count; + int status; + int ret; + + if (argc != 2) { + usage(); + return 0; + } + + cabi_id = atol (argv[1]); + + if ((ret = cabi_get_status(cabi_id, &status, &count)) != CABI_SUCCESS) { + printf ("cabi_get_status: Error (%d)\n", ret); + return 1; + } + + switch (status) { + case 0: + printf("cabi_id(%ld) now status = block(unblock), block count = %lu\n", + cabi_id, count); + break; + case 1: + printf("cabi_id(%ld) now status = block(block), block count = %lu\n", + cabi_id, count); + break; + case 2: + printf("cabi_id(%ld) now status = signal(before), send signal count = %lu\n", + cabi_id, count); + break; + case 3: + printf("cabi_id(%ld) now status = signal(after), send signal count = %lu\n", + cabi_id, count); + break; + default: + break; + } + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_get_used_time.c linux-2.4.20-cabi/drivers/cabi/examples/cb_get_used_time.c --- linux-2.4.20/drivers/cabi/examples/cb_get_used_time.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_get_used_time.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,40 @@ +/* + * This is sample program for CABI system. + * get bind pid. + */ + +#include +#include +#include +#include + +extern int cabi_get_used_time(unsigned long cabi_id, unsigned long long *nanosec); + +void usage(void) { + printf ("Usage: cabi_get_used_time [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + unsigned long cabi_id; + unsigned long long nanosec; + int ret; + + if (argc != 2) { + usage(); + return 0; + } + + cabi_id = atol (argv[1]); + + if ((ret = cabi_get_used_time(cabi_id, &nanosec)) != CABI_SUCCESS) { + printf ("cabi_get_used_time: Error (%d)\n", ret); + return 1; + } + + printf("used cpu time for last period = %llu [nsec]\n", nanosec); + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_overload_create.c linux-2.4.20-cabi/drivers/cabi/examples/cb_overload_create.c --- linux-2.4.20/drivers/cabi/examples/cb_overload_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_overload_create.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,134 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +int count = 0; + +void usage(void) { + printf ("Usage: cabi_overload_create [overload_time(us)] [ovlerload_period(us)]\n"); + printf ("--------------------------------------------------\n"); + printf (" [overload_time(us)] : overload cpu performance time (usec)\n"); + printf (" [overload_period(us)] : overload cycle time (usec)\n"); + printf (" [overload_time] / [overload_period] * 100 : overload limit persents.\n"); +} + +void sig(int sig) +{ + printf ("signal %d received. count(%d)\n", sig, count); + count++; +} + + +void loop(void) +{ + int i; + signal(SIGCONT, sig); + for (;; i++) { + /* printf("%02d: prog running...\n", i); */ + sleep (2); + } +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t admin; + long long cpu_time, cpu_period; + + struct cabi_uaccount *ucabi; + cabi_account_t cabi = NULL_ACCOUNT; + int status; + + if (argc != 3) { + usage(); + return 0; + } + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a resource set */ + ucabi = malloc (sizeof(struct cabi_uaccount)); + + /* make admin process */ + if ((admin = fork()) == -1) { + perror("fork()"); + return 1; + } + else if (admin > IDLE_PROCESS) { + /* this is parent */ + printf ("AO PID = %d\n", getpid()); + printf ("Admin PID = %d\n", admin); + waitpid(-1, &status, WNOHANG); + } else { + printf ("Admin start..pid %d\n", getpid()); + loop(); + } + + printf ("Overload Create!\n"); + + /* set scheduling and enforce mode */ +/* ucabi->cabi_param.term_act = CABI_TERM_SIGNAL; */ + ucabi->cabi_param.cabi_signal.pid = admin; + ucabi->cabi_param.cabi_signal.sig = SIGCONT; + + printf ("cabi_param.bind_proc_type (%x)\n", + ucabi->cabi_param.bind_proc_type); + + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + if ((ret = cabi_overload_create (ucabi)) == CABI_SUCCESS) { + printf ("account set create[SIGNAL]. object_id (%d)" + "cabi object address (0x%x) , user cabi address(0x%x)\n", + (int)ucabi->cabi_id, (int)cabi, (int)ucabi); + } else { + kill(admin, SIGKILL); + printf ("Kill admin process (pid = %d)\n", admin); + printf ("cabi_account_create failed.(%d)\n", ret); + return 1; + } + + if (ucabi->cabi_id != OVERLOAD_CABI_ID) { + printf ("cabi_account_create faild on cpu %p\n", cabi); + return 1; + } + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_overload_destroy.c linux-2.4.20-cabi/drivers/cabi/examples/cb_overload_destroy.c --- linux-2.4.20/drivers/cabi/examples/cb_overload_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_overload_destroy.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +extern int cabi_overload_destroy(void); + +int main (void) +{ + int ret; + + if ((ret = cabi_overload_destroy()) == CABI_SUCCESS) { + printf("overload destroy success.\n"); + } else { + printf("overload destroy faild. (%d)\n", ret); + } + return ret; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_set.c linux-2.4.20-cabi/drivers/cabi/examples/cb_set.c --- linux-2.4.20/drivers/cabi/examples/cb_set.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_set.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,146 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +void usage(void) { + printf ("cabi_set:\n"); + printf (" only cpu ratio change:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)]\n"); + printf (" cabi terminate action [signel] -> [block]:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)] [term_act]\n"); + printf (" cabi terminate action [block] -> [signal]:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)] [term_act] [pid] [sig] [flag]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [cpu_time(us)] : cpu performance time (usec)\n"); + printf (" [cpu_period(us)] : cpu cycle time (usec)\n"); + printf (" [term_act] : terminate action (block=1, signal=2)\n"); + printf (" [pid] : signal receive process id\n"); + printf (" [sig] : send signal number\n"); + printf (" [flag] : default(current) or else\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + struct cabi_uaccount *ucabi; + unsigned long cabi_id; + long long cpu_time, cpu_period; + int term_act; + int sig, flag; + pid_t pid; + + sig = flag = 0; + pid = 0; + /* set accounting object id */ + switch (argc) { + case 4: + term_act = CABI_TERM_BLOCK; + break; + case 5: + term_act = atoi(argv[4]); + if(term_act != CABI_TERM_BLOCK) { + usage(); + return 1; + } + break; + case 8: + term_act = atoi(argv[4]); + break; + default: + usage(); + return 1; + } + cabi_id = atoi (argv[1]); + cpu_time = atoll (argv[2]); + cpu_period = atoll (argv[3]); + + switch (term_act) { + case CABI_TERM_BLOCK: + break; + case CABI_TERM_SIGNAL: + pid = atoi (argv[5]); + sig = atoi (argv[6]); + flag = atoi (argv[7]); + break; + default: + printf ("Invalid parameter. term_act = %d\n", term_act); + return 1; + } + printf ("Setting...\n"); + if (cabi_id == 0) { + return 1; + } + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a user cabi */ + ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)); + + if ((ret = cabi_account_get (cabi_id, ucabi)) != CABI_SUCCESS) { + printf ("cabi_account_set : cabi_id(%ld) no exist. (%d)\n", cabi_id, ret); + return 1; + } + + /* set time to the timespec */ + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + if (argc != 4) { + ucabi->cabi_param.term_act = term_act; + } + if (term_act == CABI_TERM_SIGNAL) { + ucabi->cabi_param.cabi_signal.pid = pid; + ucabi->cabi_param.cabi_signal.sig = sig; + ucabi->cabi_param.cabi_signal.flag = flag; + } + + if ((ret = cabi_account_set (cabi_id, ucabi)) == CABI_SUCCESS) { + printf ("account set. object_id (%d)", (int)cabi_id); + } else { + printf ("cabi_id = %ld : cabi_account_set failed. (%d)\n", cabi_id, ret); + return 1; + } + + printf ("TERM_ACT (%d)\n", ucabi->cabi_param.term_act); + printf ("CPU_TIME (%lu sec %02lu nsec) /CPU_PERIOD (%lu sec %02lu nsec)\n", + ucabi->cpu_time.tv_sec, + ucabi->cpu_time.tv_nsec, + ucabi->cpu_period.tv_sec, + ucabi->cpu_period.tv_nsec); + + free(ucabi); + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/examples/cb_unbind.c linux-2.4.20-cabi/drivers/cabi/examples/cb_unbind.c --- linux-2.4.20/drivers/cabi/examples/cb_unbind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/examples/cb_unbind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_unbind [pid]\n"); + printf ("--------------------------------------------------\n"); + printf (" [pid] : unbind process id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + if (argc != 2) { + usage(); + return 0; + } + + pid = (pid_t) atoi (argv[1]); + printf ("cabi unbind pid: %d\n", pid); + + // Dettach this process from accounting obiect + if ((ret = cabi_account_unbind(pid)) != CABI_SUCCESS) { + printf ("unbind faild.(%d)\n", ret); + } else { + printf ("unbaind succeed.\n"); + } + + return 0; +} diff -Nru linux-2.4.20/drivers/cabi/lib/Makefile linux-2.4.20-cabi/drivers/cabi/lib/Makefile --- linux-2.4.20/drivers/cabi/lib/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/Makefile 2005-03-11 22:20:29.000000000 +0900 @@ -0,0 +1,30 @@ +INSTALL = /usr/bin/install +CROSS_COMPILE = +DESTDIR = +KERNELDIR = ../../.. +INCLUDEDIR = /usr +CC = $(CROSS_COMPILE)gcc -g +AR = $(CROSS_COMPILE)ar +RANLIB = $(CROSS_COMPILE)ranlib +SOURCES = $(wildcard *.c) +OBJS = $(SOURCES:.c=.o) +CFLAGS = -DCONFIG_CABI -O2 -Wall -I$(INCLUDEDIR)/include -I$(KERNELDIR)/include + +all: libcabi.so libcabi.a + +libcabi.a: $(OBJS) + $(AR) -r libcabi.a $(OBJS) + $(RANLIB) libcabi.a + +libcabi.so: $(OBJS) + $(CC) -fPIC $(OBJS) -shared -o libcabi.so + +clean: + rm -rf $(OBJS) libcabi.so libcabi.a + +install: libcabi.so libcabi.a + $(INSTALL) libcabi.a $(DESTDIR)/lib/libcabi.a + $(INSTALL) libcabi.so $(DESTDIR)/lib/libcabi.so + $(INSTALL) -d $(DESTDIR)/usr/include/cabi + $(INSTALL) -c -m 644 $(KERNELDIR)/include/cabi/cabi.h $(DESTDIR)/usr/include/cabi/cabi.h + $(INSTALL) -c -m 644 $(KERNELDIR)/include/cabi/cabi_error.h $(DESTDIR)/usr/include/cabi/cabi_error.h diff -Nru linux-2.4.20/drivers/cabi/lib/README.cabi linux-2.4.20-cabi/drivers/cabi/lib/README.cabi --- linux-2.4.20/drivers/cabi/lib/README.cabi 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/README.cabi 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,11 @@ +README file for the cabi library. +=================================== +This file describes the brief instruction abount the cabi library +install. + +Before make, please add the link for kernel for header +directories as follows. + +#ln -sf /usr/src/linux/include/linux /usr/include/linux +#ln -sf /usr/src/linux/asm-i386 /usr/include/asm + diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_bind_pgid.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_bind_pgid.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_bind_pgid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_bind_pgid.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,14 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ +#define __LIBRARY__ +#include +/* + * int sys_cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid) + */ +_syscall2(int, cabi_account_bind_pgid, unsigned long, cabi_id, pid_t, pgid) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_bind_pid.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_bind_pid.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_bind_pid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_bind_pid.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include + +/* + * int sys_cabi_account_bind_pid(unsigned long cabi_id, pid_t pid) + * + */ +_syscall2(int, cabi_account_bind_pid, unsigned long, cabi_id, pid_t, pid) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_create.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_create.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_create.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,18 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include + +/* + * int sys_cabi_account_create(cabi_object_t objectid, cabi_account_t cpu) + */ +_syscall1(int, cabi_account_create, struct cabi_uaccount *, ucabi) + + diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_destroy.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_destroy.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_destroy.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,16 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include + +/* + * int sys_cabi_account_destroy (unsigned long cabi_id) + */ +_syscall1(int, cabi_account_destroy, unsigned long, cabi_id) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_get.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_get.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_get.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_get.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,16 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include + +/* + * cabi_uaccount_t sys_cabi_account_get (unsigned long cabi_id, cabi_uaccount_t, ucabi) + */ +_syscall2(int, cabi_account_get, unsigned long, cabi_id, cabi_uaccount_t, ucabi) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_set.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_set.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_set.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_set.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,16 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include + +/* + * int sys_cabi_account_set (unsigned long cabi_id, struct cabi_uaccount_t *cpu) + */ +_syscall2(int, cabi_account_set, unsigned long, cabi_id, struct cabi_uaccount *, ucabi) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_account_unbind.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_unbind.c --- linux-2.4.20/drivers/cabi/lib/cabi_account_unbind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_account_unbind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_unbind (pid_t pid) + */ +_syscall1(int, cabi_account_unbind, pid_t, pid) diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_create_bind.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_create_bind.c --- linux-2.4.20/drivers/cabi/lib/cabi_create_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_create_bind.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,83 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include +/* + * int cabi_overload_create(cabi_uaccount_t ucabi) + */ + +extern int cabi_account_create (cabi_uaccount_t ucabi); +extern int cabi_account_bind_pid(unsigned long cabi_id, pid_t pid); +extern int cabi_account_destroy(unsigned long cabi_id); + + +int +cabi_create_bind (cabi_uaccount_t ucabi, pid_t pid) +{ + int retval = -EPERM; + + + /* If ucabi has not valid address. */ + if (!ucabi) { + return CABI_EINVAL; + } + + if (ucabi->cabi_param.bind_proc_type == BIND_IDLE_PROC) { + return CABI_EINVAL; + } + if (ucabi->cabi_param.term_act == CABI_TERM_NONE) { + ucabi->cabi_param.term_act = CABI_TERM_BLOCK; + } + + /* call cabi_account_create() */ + if (!(retval = cabi_account_create (ucabi))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind: account set create. object_id (%d)" + "user cabi address (0x%x)\n", + (int) ucabi->cabi_id, (int)ucabi); +#endif + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind failed. (%d)\n", retval); +#endif + goto error; + } + + + if (pid < 0) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind: invalid pid(%d)\n", + (int)pid); +#endif + retval = CABI_EINVAL; /* Invalid argument */ + goto error; + } + + /* call cabi_account_bind_pid */ + if (!(retval = cabi_account_bind_pid(ucabi->cabi_id, pid))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int) ucabi->cabi_id, pid); +#endif + return CABI_SUCCESS; + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid() failed.\n"); +#endif + cabi_account_destroy(ucabi->cabi_id); + } + +error: + return retval; +} + + diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_get_bind_pid.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_bind_pid.c --- linux-2.4.20/drivers/cabi/lib/cabi_get_bind_pid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_bind_pid.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,61 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include +#include + +/* + * int cabi_get_bind_pid(unsigned long cabi_id, unsigned int *conut, int *pidlist) + */ + +#define PROC_PATH "/proc/cabi/" +#define CABI_BIND_PID "/bind_pid" +#define BUF_SIZE 128 + +int cabi_get_bind_pid(unsigned long cabi_id, unsigned int *count, int *pidlist) +{ + FILE *fp; + int i; + char cabi_proc_bind_pid_path[BUF_SIZE]; + char buf[BUF_SIZE]; + + memset (cabi_proc_bind_pid_path, 0x00, sizeof(cabi_proc_bind_pid_path)); + sprintf (cabi_proc_bind_pid_path,"%s%ld%s", PROC_PATH, + cabi_id, + CABI_BIND_PID); + + if ((fp = fopen (cabi_proc_bind_pid_path, "r")) == NULL) + return CABI_ENOEXIST; + + if (*count == 0) { + while (1) { + if (fgets (buf, BUF_SIZE, fp) == NULL) + break; + else + *count += 1; + } + } else { + for (i = 0; i < *count; i++) { + if(fgets (buf, BUF_SIZE, fp) == NULL) + break; + else { + strtok(buf, "\n"); + pidlist[i] = atoi(buf); + } + } + *count = i; + } + + fclose (fp); + + return CABI_SUCCESS; +} diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_get_status.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_status.c --- linux-2.4.20/drivers/cabi/lib/cabi_get_status.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_status.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,48 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include +#include + +/* + * int cabi_get_status(unsigned long cabi_id, int *status, unsigned long *count) + */ + +#define PROC_PATH "/proc/cabi/" +#define CABI_TERM_ACT "/term_act" +#define BUF_SIZE 128 + +int cabi_get_status(unsigned long cabi_id, int *status, unsigned long *count) +{ + FILE *fp; + char cabi_proc_term_act_path[BUF_SIZE]; + char buf[BUF_SIZE]; + + memset (cabi_proc_term_act_path, 0x00, sizeof(cabi_proc_term_act_path)); + sprintf (cabi_proc_term_act_path,"%s%ld%s", PROC_PATH, + cabi_id, + CABI_TERM_ACT); + + if ((fp = fopen (cabi_proc_term_act_path, "r")) == NULL) + return CABI_ENOEXIST; + + fgets (buf, BUF_SIZE, fp); + strtok (buf, "\n"); + *status = atoi(buf); + fgets (buf, BUF_SIZE, fp); + strtok (buf, "\n"); + *count = (unsigned long)atoll(buf); + + fclose (fp); + + return CABI_SUCCESS; +} diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_get_used_time.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_used_time.c --- linux-2.4.20/drivers/cabi/lib/cabi_get_used_time.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_get_used_time.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,63 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include +#include + +/* + * int cabi_get_used_time(unsigned long cabi_id, unsigned long long *nanosec) + */ + +#define PROC_PATH "/proc/cabi/" +#define CABI_STATUS "/status" +#define BUF_SIZE 128 +#define NANOSEC 1000000000 +#define MICRO2NANO 1000 +#define DEV_SEC_STRLEN 6 + +int cabi_get_used_time(unsigned long cabi_id, unsigned long long *nanosec) +{ + FILE *fp; + unsigned long long utime_usec, utime_sec; + int utime_len; + char cabi_proc_status_path[BUF_SIZE]; + char buf[BUF_SIZE]; + + utime_usec = utime_sec = 0; + utime_len = 0; + memset (cabi_proc_status_path, 0x00, sizeof(cabi_proc_status_path)); + sprintf (cabi_proc_status_path,"%s%ld%s", PROC_PATH, + cabi_id, + CABI_STATUS); + + if ((fp = fopen (cabi_proc_status_path, "r")) == NULL) + return CABI_ENOEXIST; + + fgets (buf, BUF_SIZE, fp); + fgets (buf, BUF_SIZE, fp); + + strtok (buf, " "); + + utime_len = strlen (buf); + if (utime_len > DEV_SEC_STRLEN) { + utime_usec = (unsigned long long)atoll (buf + utime_len - DEV_SEC_STRLEN); + buf[utime_len - DEV_SEC_STRLEN] = 0x00; + utime_sec = (unsigned long long)atoll (buf); + } else { + utime_usec = (unsigned long long)atoll (buf); + } + *nanosec = utime_sec * NANOSEC + utime_usec * MICRO2NANO; + + fclose (fp); + + return CABI_SUCCESS; +} diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_overload_create.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_overload_create.c --- linux-2.4.20/drivers/cabi/lib/cabi_overload_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_overload_create.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,79 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include + +/* + * int cabi_overload_create(cabi_uaccount_t ucabi) + */ + +extern int cabi_account_create (cabi_uaccount_t ucabi); +extern int cabi_account_bind_pid(unsigned long cabi_id, pid_t pid); + +int +cabi_overload_create (cabi_uaccount_t ucabi) +{ + pid_t pid; + int ret; + + /* if ucabi has not valid address. */ + if (!ucabi) { + return CABI_EINVAL; + } + /* set bind_proc_type */ + ucabi->cabi_param.bind_proc_type = BIND_IDLE_PROC; + /* set term_act */ + ucabi->cabi_param.term_act = CABI_TERM_SIGNAL; + + /* create overload AO */ + if (!(ret = cabi_account_create (ucabi))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "overload account set create. object_id (%d)" + "user cabi address (0x%x)\n", + (int) ucabi->cabi_id, (int)ucabi); +#endif + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "overload cabi_account_create failed. (%d)\n", + ret); +#endif + return ret; + } + + /* if the system call has been success, then bind the idle process. */ + if (ucabi->cabi_id != OVERLOAD_CABI_ID) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi object_id(%d) did not set. error return.\n", (int) ucabi->cabi_id); +#endif + if(ucabi->cabi_id) + cabi_account_destroy(ucabi->cabi_id); + return CABI_EINVAL; + } + + /* set the idle process */ + pid = IDLE_PROCESS; + + /* bind idle process */ + if (!(ret = cabi_account_bind_pid(ucabi->cabi_id, pid))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int) ucabi->cabi_id, pid); +#endif + return CABI_SUCCESS; + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid() [idle] failed.\n"); +#endif + cabi_account_destroy(ucabi->cabi_id); + return ret; + } +} diff -Nru linux-2.4.20/drivers/cabi/lib/cabi_overload_destroy.c linux-2.4.20-cabi/drivers/cabi/lib/cabi_overload_destroy.c --- linux-2.4.20/drivers/cabi/lib/cabi_overload_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/drivers/cabi/lib/cabi_overload_destroy.c 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,42 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include + +/* + * int cabi_overload_destroy(void) + */ + +extern int cabi_account_unbind(pid_t pid); +extern int cabi_account_destroy(unsigned long cabi_id); + +int +cabi_overload_destroy(void) +{ + pid_t pid = IDLE_PROCESS; + int ret; + + if ((ret = cabi_account_unbind(pid)) != CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi_overload_destroy : unbind error. (%d)\n", ret); +#endif + return ret; + } + if ((ret = cabi_account_destroy(OVERLOAD_CABI_ID)) != CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi_overload_destroy : destroy error. (%d)\n", ret); +#endif + return ret; + } + + return ret; +} diff -Nru linux-2.4.20/drivers/ide/ide-cd.h linux-2.4.20-cabi/drivers/ide/ide-cd.h --- linux-2.4.20/drivers/ide/ide-cd.h 2002-08-03 09:39:44.000000000 +0900 +++ linux-2.4.20-cabi/drivers/ide/ide-cd.h 2005-03-11 20:00:09.000000000 +0900 @@ -437,7 +437,7 @@ byte curlba[3]; byte nslots; - __u8 short slot_tablelen; + short slot_tablelen; }; diff -Nru linux-2.4.20/fs/proc/generic.c linux-2.4.20-cabi/fs/proc/generic.c --- linux-2.4.20/fs/proc/generic.c 2002-08-03 09:39:45.000000000 +0900 +++ linux-2.4.20-cabi/fs/proc/generic.c 2005-03-11 20:00:09.000000000 +0900 @@ -487,8 +487,11 @@ if (ent) { ent->proc_fops = &proc_dir_operations; ent->proc_iops = &proc_dir_inode_operations; - - proc_register(parent, ent); + + if (proc_register(parent, ent) < 0) { + kfree(ent); + ent = NULL; + } } return ent; } diff -Nru linux-2.4.20/include/asm-i386/unistd.h linux-2.4.20-cabi/include/asm-i386/unistd.h --- linux-2.4.20/include/asm-i386/unistd.h 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/include/asm-i386/unistd.h 2005-03-11 20:00:09.000000000 +0900 @@ -258,6 +258,16 @@ #define __NR_free_hugepages 251 #define __NR_exit_group 252 +#ifdef CONFIG_CABI +#define __NR_cabi_account_create 261 +#define __NR_cabi_account_destroy 262 +#define __NR_cabi_account_bind_pid 263 +#define __NR_cabi_account_bind_pgid 264 +#define __NR_cabi_account_unbind 265 +#define __NR_cabi_account_get 266 +#define __NR_cabi_account_set 267 +#endif /* CONFIG_CABI */ + /* user-visible error numbers are in the range -1 - -124: see */ #define __syscall_return(type, res) \ diff -Nru linux-2.4.20/include/cabi/cabi.h linux-2.4.20-cabi/include/cabi/cabi.h --- linux-2.4.20/include/cabi/cabi.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/include/cabi/cabi.h 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,519 @@ +#ifndef CABI_CABI_H +#define CABI_CABI_H + +#undef DEBUG_CABI +/* #define DEBUG_CABI 1 *//* enable debug code */ +#ifdef DEBUG_CABI +#define DEBUG_CABI_REPLENISH_TIMER 1 +#define DEBUG_CABI_ENFORCE_TIMER 1 +#define DEBUG_CABI_ENFORCE_TIMER_START 1 + /**/ +#define DEBUG_CABI_ENFORCE 1 +#define DEBUG_CABI 1 +#endif /*DEBUG_CABI */ + +/* for debug test */ +#ifdef DEBUG_TEST +#define DEBUG_TEST_PARAM 1 +#endif + +/* for library test */ +#ifdef DEBUG_CABILIB +#undef DEBUG_CABILIB +#endif + +#undef MONTAVISTA_LINUX +#ifdef CONFIG_X86 +#include +#endif /* #ifdef CONFIG_X86 */ +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else +#include +#include +#include +#include +#endif + +/* + * Types and defines + */ +typedef unsigned long long *cpu_tick_t; +typedef unsigned long long cpu_tick_data_t; + +#define NANOSEC 1000000000L +#define MICROSEC 1000000L +#define MILISEC 1000L + +/* for parameter check */ +#define NANO_PER_MICRO 1000 +#define CABI_TICK_MAX 0xFFFFFFFFFFFFFFFFULL +#define CABI_TIME_SEC_MAX (long)(0x7FFFFFFF / 1000) + +#ifdef CONFIG_X86 +static inline void +cabi_rdtsc(cpu_tick_t data_p) +{ +#if 1 + rdtscll(*data_p); +#else + rdtsc(*(int *) (data_p), *(((int *) data_p) + 1)); +#endif +} +#else +#define CABI_CLOCK 1000000000 +#endif /* #ifdef CONFIG_X86 */ + +/* + * CPU account argument parameter + */ +enum cabi_terminate_action { + CABI_TERM_NONE = 0x0, + CABI_TERM_BLOCK = 0x1, + CABI_TERM_SIGNAL = 0x2, + CABI_TERM_UNKNOWN = 0x3, +}; + +typedef enum cabi_terminate_action cabi_term_act_t; + +enum cabi_bind_proc_type { + BIND_NORMAL_PROC = 0x0, + BIND_IDLE_PROC = 0x1, +}; + +typedef enum cabi_bind_proc_type cabi_bind_type_t; + +struct cabi_param { + cabi_term_act_t term_act; /* termnate action */ + struct { + pid_t pid; /* process id */ + int sig; /* signal number */ + int flag; /* default(current) or else */ + } cabi_signal; + cabi_bind_type_t bind_proc_type; /* process bind type */ +}; + +typedef struct cabi_param cabi_param_data_t; +typedef struct cabi_param *cabi_param_t; +typedef unsigned long cabi_object_t; + +enum cabi_term_act_status { + CABI_UNBLOCK = 0, + CABI_BLOCKED = 1, + CABI_SIGNALBFR = 2, + CABI_SIGNALAFT = 3, + CABI_UNKNOWN = 0xFF, +}; +typedef enum cabi_term_act_status term_act_status_t; + +#define CABI_SIGNALBFR 2 +#define CABI_SIGNALAFT 3 + +#define CABI_SEND_DEFL 0 +#define CABI_SEND_PID 1 +#define CABI_SIG_DEFL 0 /* or SIGCONT ? */ + +#define CABI_SIGFLAG(cabi) ((cabi)->cabi_param.cabi_signal.flag) +#define CABI_SIGPID(cabi) ((cabi)->cabi_param.cabi_signal.pid) +#define CABI_SIGNUM(cabi) ((cabi)->cabi_param.cabi_signal.sig) + +#define SIGNAL_ON 1 +#define SIGNAL_OFF 0 + +#define LANDOM_BYTES 1 +#define OVERLOAD_CABI_ID 1 +#define FIRST_CABI_ID 2 +#define IDLE_PROCESS 0 +#define CABI_ID_MAX 2147483647 +#define CABI_PROC_ENTRIES 4 + +/* + * for user applications + */ +struct cabi_uaccount { + cabi_object_t cabi_id; + cabi_param_data_t cabi_param; + struct timespec cpu_time; + struct timespec cpu_period; +}; +typedef struct cabi_uaccount *cabi_uaccount_t; + +#ifdef __KERNEL__ +/* + * NULL not running + * RUNNING running + * DEPLETED not running and depleted + * RUNNING|DEPLETED running but depleted + */ +enum cabi_account_state { + CABI_IS_NULL = 0x000, /* not running */ + CABI_IS_RUNNING = 0x001, /* actually running */ + CABI_IS_DEPLETED = 0x010, /* it's empty */ + CABI_IS_OVERLOAD = 0x100, /* overloading */ +}; +typedef enum cabi_account_state cabi_account_state_t; +typedef unsigned long cabi_overload_t; + +/* + * include/linux/sched.h, we add cabi_info address. + * this is the reference macros. + */ +#define TASK_ACCOUNT(tsk) ((cabi_account_t)((tsk)->cabi_info)) +#define CABI_ID(tsk) ((unsigned long)((tsk)->cabi_info->cabi_id)) + +/* + * Internal data structure to keep track of cpu capacity usages. + */ +typedef unsigned long cpu_capacity_t; +typedef unsigned long long cpu_capacity_quad_t; + +#define CAPACITY_INT(x) ((x)/100) +#define CAPACITY_FRAC(x) ((x)-(x/100)*100) +#define INT2CAPACITY(x) ((x)*10000) +#define CAPACITY2INT(x) ((x)/10000) +#define PERCENT2CAPACITY(x) ((x)*100) +#define CAPACITY_OF(c,t) (INT2CAPACITY(c)/(t)) +#define CPU_CAPACITY_MAX PERCENT2CAPACITY(100) +#define FULLCAPACITY 100 + +/* + * struct cabi_account + */ +struct cabi_account { + + cabi_account_state_t cpu_state; /* state */ + cabi_param_data_t cabi_param; /* scheduling & terminate */ + cabi_object_t cabi_id; /* object id */ + cabi_overload_t overload; /* overload flag */ + + /* Linux dependent part */ + struct list_head cpu_proc_list; /* list of processes */ + + /* procfs entry under /proc/cpu/ */ + struct proc_dir_entry *cpu_proc_entry; + struct proc_dir_entry *cpu_log_proc_entry; + struct timer_list cpu_replenish_tmr; + + cpu_tick_data_t cpu_period_used_ticks; /* CPU ticks already used + in the current period */ + cpu_tick_data_t cpu_period_start_ticks; /* remember start ticks for + the current invocation */ + cpu_tick_data_t cpu_period_available_ticks; /* CPU ticks that can be + * used for this period */ + wait_queue_head_t depleted_wait; /* for enforcement */ + + /* execution statistics */ + cpu_tick_data_t cpu_period_prev_used_ticks; + cpu_tick_data_t cpu_total_used_ticks; + cpu_capacity_t cpu_max_utilization; + cpu_capacity_t cpu_min_utilization; + struct { + unsigned long total_count; /* replenishment count */ + cpu_capacity_quad_t total_utils; /* sum of utilizations */ + } cpu_average; + + /* static data */ + struct list_head cpu_link; /* link all cpu accounts */ + struct timespec cpu_time; + struct timespec cpu_period; + cpu_tick_data_t cpu_time_ticks; /* ticks for cpu_time */ + cpu_tick_data_t cpu_period_ticks; /* ticks for cpu_period */ + cpu_capacity_t cpu_capacity; /* requested capacity */ + + term_act_status_t term_act_status; + unsigned long block_count, signal_count; + int signal_block; + +}; +typedef struct cabi_account *cabi_account_t; + +#define NULL_ACCOUNT ((cabi_account_t)0) +#define NULL_UACCOUNT ((cabi_uaccount_t)0) +#define NULL_ACCOUNT_ID 0x0 + +/* Spin Lock & Unlock + * Usage: + * { + * unsigned long flags; + * cabi_spin_lock(flags); + * + * cabi_spin_unlock(flags); + * } + */ +extern spinlock_t cabi_lock; +#define cabi_spin_lock(flags) spin_lock_irqsave(&cabi_lock, flags) +#define cabi_spin_unlock(flags) spin_unlock_irqrestore(&cabi_lock, flags) + +/* + * timer for accounts: + * replenishment ... periodic + * expiration ... aperiodic + * + * - tmr_expire: holds an absolute time in CPU tick when its timer expires. + * - tmr_handler: keeps the pointer to a handler funcion which is called + * when its timer expires. + * + */ +extern void cabi_replenish_timer_init(cabi_account_t, cpu_tick_t); +extern void cabi_replenish_timer_cancel(cabi_account_t); +extern void cabi_enforce_timer_start(cabi_account_t, cpu_tick_t); +extern void cabi_enforce_timer_cancel(void); +extern void cabi_enforce_timer_init(struct timer_list *); +extern void cabi_timer_start(void); +extern int cabi_send_signal(cabi_account_t, int, int); + +/* + * Global Variables and params + */ +extern cpu_tick_data_t cabi_timer_adjust; +extern cpu_tick_data_t cabi_cpu_ticks_per_second; +extern cpu_tick_data_t cabi_cpu_ticks_per_jiffy; + +#define CABI_USECS_PER_JIFFY (1000016L/HZ) /* 10000 (HZ=100) */ +#define CABI_NANOSECS_PER_JIFFY (1000016762L/HZ) /* 10000167 (HZ=100) */ + +/* + * Conversions between tick and nanosec + * cabi_cpu_ticks_per_second:NANOSEC = ticks:nanosec + */ +static inline void +nanosec2tick(cpu_tick_t ns, cpu_tick_t tick) +{ + cpu_tick_data_t microsec = MICROSEC; + unsigned long long us; + us = (*ns) / NANO_PER_MICRO; + *tick = (us * cabi_cpu_ticks_per_second) / microsec; +} + +static inline cpu_tick_data_t +tick2nanosec(cpu_tick_t tick) +{ + cpu_tick_data_t microsec = MICROSEC; + unsigned long long us; + us = ((*tick) * microsec) / cabi_cpu_ticks_per_second; + return (us * NANO_PER_MICRO); +} + +static inline void +tick2ts(cpu_tick_t tick, struct timespec *ts) +{ + cpu_tick_data_t ns; + ts->tv_sec = *tick / cabi_cpu_ticks_per_second; + ns = *tick - (cabi_cpu_ticks_per_second * ts->tv_sec); + ts->tv_nsec = tick2nanosec(&ns); +} + +#ifndef CONFIG_X86 +static inline void +jiffies2tick(cpu_tick_t tick) +{ + unsigned long long milisec = MILISEC; + *tick = ((unsigned long long) jiffies * 10) * + (cabi_cpu_ticks_per_second / milisec); +} +#endif /* #ifndef CONFIG_X86 */ + +static inline void +cabi_rdticks(cpu_tick_t data_p) +{ +#ifdef CONFIG_X86 + cabi_rdtsc(data_p); +#else + jiffies2tick(data_p); +#endif /* #ifdef CONFIG_X86 */ +} + +/* + * Conversion between tick and usec + * cabi_cpu_ticks_per_second:MICROSEC = ticks:usec + */ +static inline void +tick2usec(cpu_tick_t tick, cpu_tick_t us) +{ + cpu_tick_data_t ms = MILISEC; + *us = ((*tick) * ms) / (cabi_cpu_ticks_per_second / ms); +} + +static inline unsigned long +TICK2USEC(cpu_tick_t tick) +{ + cpu_tick_data_t us; + tick2usec(tick, &us); + return (unsigned long) us; +} + +/* + * Enable/Disable CABI hooks + */ +static void inline +cabi_enable(void) +{ + extern void cabi_enable_schedule_cpu(void); + extern void cabi_enable_isr(void); + + cabi_enable_schedule_cpu(); + cabi_enable_isr(); +} + +static void inline +cabi_disable(void) +{ + extern void cabi_disable_schedule_cpu(void); + extern void cabi_disable_isr(void); + + cabi_disable_schedule_cpu(); + cabi_disable_isr(); +} + +/* + * Start/Stop accounting + */ +void cabi_start_account(cabi_account_t); +void cabi_stop_account(cabi_account_t, cpu_tick_t); +void cabi_account_enforce(cabi_account_t); +void cabi_account_replenish(cabi_account_t, struct timespec *); +void cabi_account_sleep_on(cabi_account_t); + +/* proc file systems */ +extern int cabi_account_read_proc(cabi_account_t, char *); +extern int cabi_account_read_bindpid_proc(cabi_account_t, char *); +extern int cabi_account_read_block_proc(cabi_account_t, char *); +extern int cabi_account_read_time_proc(cabi_account_t, char *); + +static inline int +cabi_account_depleted(cabi_account_t cabi) +{ + if (cabi) { + return (cabi->cpu_state & CABI_IS_DEPLETED); + } + return 0; +} + +static inline int +cabi_account_overload(cabi_account_t cabi) +{ + if (cabi) { + if (cabi->overload == CABI_IS_OVERLOAD) + return 1; + } + return 0; +} +extern int cabi_proc_account_create(cabi_account_t); +extern int cabi_proc_account_destroy(cabi_account_t); + +static inline int +cabi_is_overload_account(cabi_account_t cabi) +{ + if (cabi) { + if (cabi->cabi_id == OVERLOAD_CABI_ID) + return 1; + } + return 0; +} + +/* + * Scheduling type + */ +#define LINUX_RT_PRIORITY 50 /* used with SCHED_FIFO */ +#define LINUX_TS_PRIORITY 0 + +/* + * Process list + */ +struct rs_proc_list { + struct list_head rs_proc_list; + pid_t rs_proc_pid; + struct task_struct *rs_proc_task; +}; + +static inline void +rs_proc_list_apply(struct list_head *proc_list_head, + void (*func) (struct rs_proc_list *)) +{ + struct list_head *proc_list; + struct rs_proc_list *rs_proc; + + proc_list = proc_list_head->next; + while (proc_list != proc_list_head) { + /* get a rs_proc */ + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + /* do it */ + func(rs_proc); + + /* next process */ + proc_list = proc_list->next; + } +} + +#define malloc(s) kmalloc(s, SLAB_KERNEL) +#define free(p) kfree(p) +#define bzero(p, s) memset(p, 0, s) + +extern void cabi_account_sched_rt(struct rs_proc_list *); +extern void cabi_account_sched_ts(struct rs_proc_list *); + +static inline struct task_struct * +__cabi_find_process_by_pid(pid_t pid) +{ + struct task_struct *tsk = current; + + if (pid) + tsk = find_task_by_pid(pid); + return tsk; +} + +static inline struct task_struct * +__cabi_find_idle_process(pid_t pid) +{ + struct task_struct *idle; + + /* if (pid == 0) */ + idle = find_idle_process(); + if (!idle) { + idle = NULL; + return idle; + } else { + return idle; + } +} + +#else /* __KERNEL__ */ + +/* + * Types for user level applications. + */ +typedef void *cabi_account_t; +#define NULL_ACCOUNT 0 + +/* + * Function prototypes, + */ +extern int cabi_account_create(cabi_uaccount_t); +extern int cabi_account_destroy(unsigned long); +extern int cabi_account_bind_pid(unsigned long, pid_t); +extern int cabi_account_bind_pgid(unsigned long, pid_t); +extern int cabi_account_unbind(pid_t); +extern int cabi_account_get(unsigned long, cabi_uaccount_t); +extern int cabi_account_set(unsigned long, cabi_uaccount_t); + +/* + * library call + */ +extern int cabi_overload_create(cabi_uaccount_t); +extern int cabi_overload_destroy(void); +extern int cabi_create_bind(cabi_uaccount_t, pid_t); + +#endif /* __KERNEL__ */ +#endif diff -Nru linux-2.4.20/include/cabi/cabi_error.h linux-2.4.20-cabi/include/cabi/cabi_error.h --- linux-2.4.20/include/cabi/cabi_error.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.4.20-cabi/include/cabi/cabi_error.h 2005-03-11 20:00:09.000000000 +0900 @@ -0,0 +1,23 @@ +#ifndef CABI_CABI_ERROR_H +#define CABI_CABI_ERROR_H + +#define CABI_SUCCESS 0 /* Success */ +#define CABI_ERROR 1 /* Error */ + +#define CABI_SYSERR 2 /* Linux system error */ +#define CABI_EINVAL 3 /* Invalid argument */ +#define CABI_EACCESS 4 /* No use authority */ + +#define CABI_ENOMEM 5 /* Memory allocation failed. */ +#define CABI_EATTACHED 6 /* Process is still attached. */ +#define CABI_ENOAVLE 7 /* PID is registered into another AO. */ +#define CABI_EREGIST 8 /* PID is already registered into AO. */ +#define CABI_ENOBIND 9 /* PID is not bound to AO. */ +#define CABI_ENOEXIST 10 /* AO dose not exist. */ +#define CABI_EPNOEXIST 11 /* PID dose not exist. */ +#define CABI_EPGNOEXIST 12 /* PGID dose not exist. */ +#define CABI_ENOCABIID 13 /* No more cabi id exist. */ + +#define CABI_CREATE_ERR 14 /* cabi_account_create error. */ + +#endif /* CABI_CABI_ERROR_H */ diff -Nru linux-2.4.20/include/linux/sched.h linux-2.4.20-cabi/include/linux/sched.h --- linux-2.4.20/include/linux/sched.h 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/include/linux/sched.h 2005-03-11 20:00:09.000000000 +0900 @@ -418,6 +418,11 @@ /* journalling filesystem info */ void *journal_info; + +#ifdef CONFIG_CABI +/* CPU Accounting System info */ + void *cabi_info; +#endif }; /* @@ -469,6 +474,51 @@ * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) */ +#ifdef CONFIG_CABI +#define INIT_TASK(tsk) \ +{ \ + state: 0, \ + flags: 0, \ + sigpending: 0, \ + addr_limit: KERNEL_DS, \ + exec_domain: &default_exec_domain, \ + lock_depth: -1, \ + counter: DEF_COUNTER, \ + nice: DEF_NICE, \ + policy: SCHED_OTHER, \ + mm: NULL, \ + active_mm: &init_mm, \ + cpus_runnable: -1, \ + cpus_allowed: -1, \ + run_list: LIST_HEAD_INIT(tsk.run_list), \ + next_task: &tsk, \ + prev_task: &tsk, \ + p_opptr: &tsk, \ + p_pptr: &tsk, \ + thread_group: LIST_HEAD_INIT(tsk.thread_group), \ + wait_chldexit: __WAIT_QUEUE_HEAD_INITIALIZER(tsk.wait_chldexit),\ + real_timer: { \ + function: it_real_fn \ + }, \ + cap_effective: CAP_INIT_EFF_SET, \ + cap_inheritable: CAP_INIT_INH_SET, \ + cap_permitted: CAP_FULL_SET, \ + keep_capabilities: 0, \ + rlim: INIT_RLIMITS, \ + user: INIT_USER, \ + comm: "swapper", \ + thread: INIT_THREAD, \ + fs: &init_fs, \ + files: &init_files, \ + sigmask_lock: SPIN_LOCK_UNLOCKED, \ + sig: &init_signals, \ + pending: { NULL, &tsk.pending.head, {{0}}}, \ + blocked: {{0}}, \ + alloc_lock: SPIN_LOCK_UNLOCKED, \ + journal_info: NULL, \ + cabi_info: NULL, \ +} +#else /* #ifdef CONFIG_CABI */ #define INIT_TASK(tsk) \ { \ state: 0, \ @@ -511,6 +561,7 @@ alloc_lock: SPIN_LOCK_UNLOCKED, \ journal_info: NULL, \ } +#endif /* #ifdef CONFIG_CABI */ #ifndef INIT_TASK_SIZE @@ -560,6 +611,10 @@ return p; } +#ifdef CONFIG_CABI +extern struct task_struct *find_idle_process(void); +#endif + #define task_has_cpu(tsk) ((tsk)->cpus_runnable != ~0UL) static inline void task_set_cpu(struct task_struct *tsk, unsigned int cpu) diff -Nru linux-2.4.20/include/linux/sys.h linux-2.4.20-cabi/include/linux/sys.h --- linux-2.4.20/include/linux/sys.h 1995-12-11 13:56:37.000000000 +0900 +++ linux-2.4.20-cabi/include/linux/sys.h 2005-03-11 20:00:09.000000000 +0900 @@ -4,7 +4,11 @@ /* * system call entry points ... but not all are defined */ +#ifdef CONFIG_CABI +#define NR_syscalls 288 +#else #define NR_syscalls 256 +#endif /* * These are system calls that will be removed at some time diff -Nru linux-2.4.20/init/main.c linux-2.4.20-cabi/init/main.c --- linux-2.4.20/init/main.c 2002-08-03 09:39:46.000000000 +0900 +++ linux-2.4.20-cabi/init/main.c 2005-03-11 20:00:09.000000000 +0900 @@ -69,6 +69,11 @@ #include #endif +#ifdef CONFIG_CABI +extern void cabi_init(void); +#endif + + /* * Versions of gcc older than that listed below may actually compile * and link okay, but the end product can have subtle run time bugs. @@ -536,6 +541,9 @@ #ifdef CONFIG_PCMCIA init_pcmcia_ds(); /* Do this last */ #endif +#ifdef CONFIG_CABI + cabi_init(); +#endif } extern void prepare_namespace(void); diff -Nru linux-2.4.20/kernel/exit.c linux-2.4.20-cabi/kernel/exit.c --- linux-2.4.20/kernel/exit.c 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/kernel/exit.c 2005-03-11 20:00:09.000000000 +0900 @@ -21,6 +21,10 @@ #include #include +#ifdef CONFIG_CABI +#include +#endif + extern void sem_exit (void); extern struct task_struct *child_reaper; @@ -449,6 +453,18 @@ exit_sighand(tsk); exit_thread(); + +#ifdef CONFIG_CABI + if (tsk->cabi_info) { + extern void cabi_account_detach(struct task_struct *); +#ifdef DEBUG_CABI + printk("in exit, detach pid (%d) cabi(0x%x)\n", + tsk->pid, (int) tsk->cabi_info); +#endif + cabi_account_detach(tsk); + } +#endif + if (current->leader) disassociate_ctty(1); diff -Nru linux-2.4.20/kernel/fork.c linux-2.4.20-cabi/kernel/fork.c --- linux-2.4.20/kernel/fork.c 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/kernel/fork.c 2005-03-11 20:00:09.000000000 +0900 @@ -28,6 +28,11 @@ #include #include +#ifdef CONFIG_CABI +#include +#endif + + /* The idle threads do not count.. */ int nr_threads; int nr_running; @@ -748,6 +753,20 @@ nr_threads++; write_unlock_irq(&tasklist_lock); +#ifdef CONFIG_CABI + if (p->cabi_info) { + cabi_account_t cabi; + int cabi_account_attach(unsigned long, struct task_struct *); + cabi = p->cabi_info; + p->cabi_info = NULL; + cabi_account_attach(cabi->cabi_id, p); +#ifdef DEBUG_CABI + printk("in fork, attach pid (%d) cabi(0x%x)\n", p->pid, + (int) cabi); +#endif + + } +#endif if (p->ptrace & PT_PTRACED) send_sig(SIGSTOP, p, 1); diff -Nru linux-2.4.20/kernel/sched.c linux-2.4.20-cabi/kernel/sched.c --- linux-2.4.20/kernel/sched.c 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/kernel/sched.c 2005-03-11 20:00:09.000000000 +0900 @@ -30,6 +30,10 @@ #include #include +#ifdef CONFIG_CABI +#include +#endif + #include #include @@ -127,6 +131,20 @@ void scheduling_functions_start_here(void) { } +#ifdef CONFIG_CABI + +struct task_struct * find_idle_process(void) +{ + struct task_struct *idle; +#ifdef MONTAVISTA_LINUX + idle = &init_task; +#else + idle = idle_task(smp_processor_id()); +#endif + return idle; +} +#endif + /* * This is the function that decides how desirable a process is.. * You can weigh different processes against each other depending @@ -688,6 +706,38 @@ } } +#ifdef CONFIG_CABI + { + +#ifdef DEBUG_CABI + cabi_account_t prev_cabi = TASK_ACCOUNT(prev); + cabi_account_t next_cabi = TASK_ACCOUNT(next); + if (prev_cabi) { + printk("prev_cabi[%d] prev[%d] next[%d]\n", + (int) prev_cabi->cabi_id, + prev->pid, next->pid); + } + if (next_cabi) { + printk("next_cabi[%d] prev[%d] next[%d]\n", + (int) next_cabi->cabi_id, + prev->pid, next->pid); + } + + if (prev->pid == 0 || next->pid == 0) { + if (TASK_ACCOUNT(prev) || TASK_ACCOUNT(next)) { + printk("prev[%d] next[%d]\n", + prev->pid, next->pid); + + } + } +#endif + extern void (*cabi_schedule_hook)(struct task_struct *, + struct task_struct *); + if (cabi_schedule_hook) + cabi_schedule_hook(prev, next); + + } +#endif /* * This just switches the register state and the * stack. @@ -1324,6 +1374,11 @@ smp_processor_id(), current->pid); del_from_runqueue(current); } + +#ifdef CONFIG_CABI + printk("idle task pid [%d] (0x%x)\n", + current->pid, (int)current); +#endif sched_data->curr = current; sched_data->last_schedule = get_cycles(); clear_bit(current->processor, &wait_init_idle); diff -Nru linux-2.4.20/net/core/rtnetlink.c linux-2.4.20-cabi/net/core/rtnetlink.c --- linux-2.4.20/net/core/rtnetlink.c 2002-11-29 08:53:15.000000000 +0900 +++ linux-2.4.20-cabi/net/core/rtnetlink.c 2005-03-11 20:00:09.000000000 +0900 @@ -394,7 +394,7 @@ * Malformed skbs with wrong lengths of messages are discarded silently. */ -extern __inline__ int rtnetlink_rcv_skb(struct sk_buff *skb) +static __inline__ int rtnetlink_rcv_skb(struct sk_buff *skb) { int err; struct nlmsghdr * nlh;