Open Source Cloud Authors: Pat Romanski, Liz McMillan, Yeshim Deniz, Elizabeth White, Zakia Bouachraoui

Related Topics: Open Source Cloud

Open Source Cloud: Article

Implementing the Race Timer

Implementing the Race Timer

This is an excerpt from Chapter 11 of Embedded Linux by Craig Hollabaugh, published by Addison-Wesley. ISBN 0672322269. No part of this excerpt may be reproduced, in any form or by any means without the prior written permission of the publisher. (c) 2002 Addison-Wesley

The Project Trailblazer engineers want to use embedded Linux for race timing to reduce data entry errors, increase efficiency and enhance the racers' experience

This chapter series explores using Linux as an event timer with 1-millisecond resolution. In Part 1 we discussed Linux timing sources and interrupt latency. Part 2 covered measuring interrupt latency on the MZ104, Part 3 was about measuring interrupt latency on the MediaEngine, and in Part 4 we discussed measuring interrupt latency on the RPX-CLLF. In this final Part we cover Implementing the Race Timer.

After the Project Trailblazer engineers resolve the average interrupt latency question, they can design the race timer. All the Project Trailblazer target boards have the input/output (I/O) and speed capability to act as the race timer. For this design, the engineers decide to use the MZ104 as the controller.

The race timer should have the following functional features:

  • It must have 1ms accuracy.
  • It should display the current race time at the finish line.
  • It should provide a status display to officials operating the timer.
  • It should use the racer's pass ID in race information.
  • It should provide the racer with a race start indicator.
  • It should log race results.
  • It should provide access to status, race time, and racer number through /proc directory entries.
The operational race scenario consists of four states:

  • Ready-On power-up, the race controller enters the ready state and awaits a racer. The racer gets ready at the starting gate. The radio frequency identification (RFID) tag reader reads the racer's lift pass ID and sends it via the RS-232 serial link. This places the controller in the set state.

  • Set-The Status LED and Racer Go LEDs turn on. The racer proceeds through the starting gate, which sends a rising-edge signal to the ACK line and generates interrupt 7. The interrupt handler routine executes, records the race start time with do_gettimeofday, schedules the bottom-half tasklet for execution, and puts the controller in the timing state.

  • Timing-The Status LED and Racer Go LEDs blink at 1-second intervals. When the racer crosses the finish line, the photo detector sends a rising-edge signal to the ACK line and generates interrupt 7. The interrupt handler routine executes, records the race finish time with do_gettimeofday, schedules the bottom-half tasklet for execution, and puts the controller in the done state.

  • Done-The Status LED and Racer Go LEDs turn off. The controller waits for another racer to enter the starting gate.

    Race Timer Interrupt Processing Using Tasklets
    Complex or lengthy interrupt processing tasks are often split into two sections. The top-half routine executes at interrupt time, performs the minimal amount of work, and schedules the remainder of work, called the bottom half routine, to be performed at a later or safer time. The top-half routine can request execution with interrupts disabled; therefore, it should execute and terminate as quickly as possible. The kernel executes bottom-half routines with interrupts enabled. With Linux kernel 2.4 and above, the preferred way to implement bottom-half routine uses tasklets.

    Tasklets are declared by using the DECLARE_TASKLET macro. This macro also associates a handler function to the tasklet. The top-half interrupt handler routine should schedule an already declared tasklet for later execution. The kernel executes the scheduled tasklet handler functions after all the interrupt handler routines complete but before execution of the scheduler.

    In the race timer design, the interrupt handler, racetimer_interrupt, schedules the race timer tasklet's handler routine, racetimer_do_tasklet, for later execution. The racetimer_do_tasklet function prints race status information to the system log, which is a somewhat lengthy process, and starts a system timer.

    Race Timer Status Display Using System Timers
    The race timer Status and Racer Go LEDs inform officials, fans, and racers of race activity. A solid on signal means the system is ready for a race to begin. Blinking LEDs mean a race is in progress. When the LEDs are off, a race is complete and the system is ready for another racer to enter the starting gate. The Project Trailblazer engineers need to figure out how to blink the LEDs at a constant 1-second rate.

    As you saw in Part 1, Linux offers five timing mechanisms, and the engineers chose to use do_gettimeofday for race timing. The race timer driver could sit in a loop calling do_gettimeofday and wait for 1 second to elapse. The race timer driver could also call a system sleep function (usleep, msleep, or sleep) and wait for 1 second to elapse. Both approaches would work, but neither is desirable. The kernel scheduler does not drive code that is executing in the kernel space. A 1-second sleep in the kernel would completely occupy the processor for 1 second, and other processing would not occur during this time. Device drivers that use sleep functions for long delays definitely affect system performance.

    Kernel timers solve long time delay problems. By using a timer, device drivers can schedule a function for execution at a future time. A device driver creates a timer, populates the timer's data, function and expires fields and then adds the timer to the kernel's timer list. The x86 kernel scans the timer list approximately 100 times per second. If the kernel's jiffies value is greater than a timer's expires field value, the kernel executes the timer's function handler. Timers operate in a one-shot mode. The kernel executes timer function handlers only once. Drivers that need periodic function execution need to reschedule their kernel timers in the timer's function handler. In the race timer, the bottom-half tasklet handler, racetimer_do_tasklet, starts the kernel timer called status_timer. One second later, the status_timer expires and the kernel executes the status_timer's function handler, status_timer_timed_out. If the race is in progress (the timing state where the LEDs blink at 1 second intervals), status_timer_timed_out toggles the Status and Racer Go LEDs, sets the status_timer.expires value, and then reschedules (via the add_timer function) status_timer for execution 1 second later. If the race has completed, status_timer_timed_out turns off the LEDs.

    Let's look at how the racetimer_x86.c device driver, shown in Listing 4, implements bottom-half interrupt processing using a scheduled tasklet and 1-second timing of the Status and Racer GO LEDs. (See Listing 4)

    You can download, compile, and test the racetimer_x86 device driver by using tbdev1. Follow these steps:

    1.   Download the racetimer_x86.c source by using wget: [email protected][509]: cd /root [email protected][510]: wget http://www.embeddedlinuxinterfacing.com/ chapters/11/racetimer_x86.c

    2.   Compile the source code by using gcc: [email protected][511]: gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include -c racetimer_x86.c -o racetimer_x86.o

    3.   Insert the device driver by using insmod: [email protected][512]: insmod racetimer_x86.o

    4.   Look for interrupt registration on Interrupt 7 and the /proc directory entries by using these commands:

    [email protected][513]: cat /proc/interrupts

    [email protected][514]: ls /proc/trailblazer/
    racer racestatus racetime

    The race timer is registered on Interrupt 7 and the /proc/trailblazer directory contains the race timer files.

    5.   Check the internal state of the race timer status: [email protected][515]: cat /proc/trailblazer/racestatus

    The output R means that the timer is in the ready state.

    6.   Start a race by simulating a racer entering the starting gate with this command:[email protected][516]: echo -n "1234" < /proc/trailblazer/racer]

    7.   Again check the internal state of the race timer status: [email protected][517]: cat /proc/trailblazer/racestatus

    The output S means that the timer is in the Set state. You can tell from this output that setting the racer number occurred correctly, and it changed the internal state to S, or set. The status LED also came on. Measure the voltage of the parallel port's D0 signal, pin 2 on the DB-25 connector. Your voltmeter should read between +3V and +5V.

    8.   Now check the race time by using this command: [email protected][518]: cat /proc/trailblazer/racetime 0.000000

    9.   The racer number is entered in the racer file, the race time is 0.00000 and the timer is in the set state. You are set to start the race. Simulate the racer proceeding through the starting gate by generating the interrupt signal on the parallel port ACK line, pin 10 on the DB-25 connector. Use a debounced switch to generate a positive going signal on the ACK line.

    With interrupt latencies in the microsecond range, Linux interrupt routines can easily count mechanical switch bounces. If you would like to see this for yourself, use a toggle switch to generate the interrupt signal on the parallel port's ACK line. Then examine the interrupt count in the /proc/interrupts file. You should see that one switch closure results in more than one interrupt. Mechanical switches alone should not be used to generate interrupt signals in interrupt-based designs or during interrupt driver testing. For testing, use a switch debounce circuit or write a device driver, again for the parallel port, that drives the ACK line from another parallel port pin. The gate_x86 device driver at www.embeddedlinuxinterfacing.com/chapters/11 generates signals for interrupt device driver testing.

    10.   Again check the internal state of the race timer status: [email protected][519]: cat /proc/trailblazer/racestatus

    The output T means that the timer is in the timing state.

    11.   Check the race time by using this command: [email protected][520]: cat /proc/trailblazer/racetime 6.331849

    You are timing a race, and 6.331849 seconds have elapsed.

    12.   Continue checking the race time: [email protected][521]: cat /proc/trailblazer/racetime 58.101223

    You are still timing the race. The status LEDs are blinking at 1-second intervals.

    13.   Simulate the racer crossing the finish line by using your debounced switch. Again, generate an interrupt signal on the parallel port's ACK line.

    14.   Check the internal state of the race timer status:
    [email protected][522]: cat /proc/trailblazer/racestatus

    The output D means the race is done.

    15.   Check the race time and the system log by using these commands:

    [email protected][523]: cat /proc/trailblazer/racetime88.141655
    [email protected][524]: grep RaceTime /var/log/messages
    Nov 26 22:54:14 tbdev1 kernel: RaceTimer: Start 1234 1006840454.722554
    Nov 26 22:55:42 tbdev1 kernel: RaceTimer: Finish 1234 1006840542.864209

    The race time of your first simulated race was 88.141655 seconds.

    16.   One last check of /proc/interrupts shows that tbdev1 received two interrupts-from the race start and finish:

    [email protected][525]: cat /proc/interrupts
    0:8262755XT-PIC timer
    1:2195XT-PIC keyboard
    2:0XT-PIC cascade
    4:6016XT-PIC serial
    7:2XT-PIC racetimer
    10:23132XT-PIC usb-uhci
    12:314556XT-PIC eth0
    14:54257XT-PIC ide0
    15:8457XT-PIC ide1

    The Project Trailblazer race timer just timed its first race!

    This chapter explores using Linux as an event timer with 1ms resolution. Linux offers several mechanisms for timing, and the do_gettimeofday function with microsecond resolution works best for the three Project Trailblazer target board processors. Whereas determining maximum interrupt latency is difficult, measuring average interrupt latency is relatively easy. Using the interrupt latency device drivers and an oscilloscope, the engineers found the average interrupt latency for the MZ104, the MediaEngine, and the RPX-CLLF to be 50ms, 10ms, and 35ms, respectively. These impressive numbers alleviated the need for the engineers to explore real-time Linux solutions.

    The racetimer_x86 device driver implements a split interrupt driver and a 1-second kernel timer. The interrupt top-half routine executes quickly, with interrupts disabled, and schedules the bottom-half tasklet for future execution. The bottom-half tasklet then performs lengthy writes to the system log and starts a 1-second reoccurring kernel timer. By using a kernel timer, the driver avoids using wait loops or sleep functions that dramatically affect system performance.

    Additional Reading
    1.   Intel, SA-1110 Microprocessor Developer's Manual, www.intel.com/design/strong/manuals/278240.htm.

    2.   Motorola, MPC860 User Manual, www.motorola.com/brdata/PDFDB/docs/MPC860UM.pdf.

    Listing 4: The racetimer_x86.c Device Driver

    * racetimer_x86 v1.0 11/25/01
    * www.embeddedlinuxinterfacing.com
    * The original location of this code is
    * http://www.embeddedlinuxinterfacing.com/chapters/11/
    * Copyright (C) 2001 by Craig Hollabaugh
    * This program is free software; you can redistribute it and/or modify it under the
    terms of the GNU Library General Public License as published by the Free Software
    Foundation; either version 2 of the License, or (at your option) any later version.
    * This program 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 Library General Public License for more details.
    * You should have received a copy of the GNU Library General Public License along with
    this program; if not, write to the Free Software Foundation, Inc., 59 Temple
    Place, Suite 330, Boston, MA 02111-1307 USA

    * racetimer_x86.c is based on procfs_example.c by Erik Mouw.
    * For more information, please see The Linux Kernel Procfs Guide, Erik Mouw
    * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html

    gcc -O2 -D__KERNEL__ -DMODULE -I/usr/src/linux/include \
    -c racetimer_x86.c -o racetimer_x86.o

    /* racetimer_x86
    * This module implements a race timer with millisecond accuracy using
    * interrupts and bottom half tasklets. The timer also drives a status
    * indicator line (parallel port DO) showing the timer's current state.
    * Controlling or accessing timer information is provided through /proc
    * directory entries.
    * Here are the timer's states
    * Ready: Timer ready for racer number entry
    * Set: Timer ready for racer to start, status indicator ON
    * Timing: Timer measuring race time, status indicator blinking 1s intervals
    * Done: Race is done, Timer ready for racer number entry
    * Interrupts or racer number entry forces a state change.
    * /proc directory entries
    * /proc/trailblazer/racernumber contains the racer number, timer isn't
    * ready until a number is written to this
    * file
    * /proc/trailblazer/racetime contains the current or last race time
    * /proc/trailblazer/racestatus contains the race timer state, R, S, T or D

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/proc_fs.h>
    #include <asm/uaccess.h>
    #include <asm/io.h>
    #include <linux/sched.h>
    #include <linux/interrupt.h>
    #include <linux/tqueue.h>

    #define MODULE_VERSION "1.0"
    #define MODULE_NAME "racetimer"

    static struct proc_dir_entry *tb_dir,
    *racer_file, *racestatus_file, *racetime_file;

    #define SPPDATAPORT 0x378
    #define STATUSLED 0x01 /* DO on the parallel port */

    struct timeval starttime, finishtime;

    unsigned char state;
    #define STATE_Ready 'R'
    #define STATE_Set 'S'
    #define STATE_Timing 'T'
    #define STATE_Done 'D'
    /* using letters here instead of numbers, cat /proc/trailblazer/racestatus
    * makes things a little easier to read */

    #define INTERRUPT 7

    struct timer_list status_timer;
    unsigned char toggle;

    #define RACERNUMBERLEN 10
    unsigned char racernumber[RACERNUMBERLEN+1];

    /* status_timer_timed_out
    * This function gets called when the status_timer expires, basically every
    * 1 second during the race (state = STATE_Timing). Its primary purpose is to
    * toggle the status line that blink the LEDs. If we're racing, we need to
    * re-schedule the timer for 1 second in the future.
    void status_timer_timed_out(unsigned long ptr)
    if (state == STATE_Timing)
    outb(toggle++ & STATUSLED, SPPDATAPORT); /* toggle the statusLED line */
    status_timer.expires = jiffies + HZ; /* 1 second intervals */
    add_timer(&status_timer); /* kicks off the next timer */
    outb(0x00, SPPDATAPORT); /* toggle off statusLED line */

    /* racetimer_do_tasklet
    * This function is the interrupt bottom-half tasklet handler. It performs
    * the lengthy processing that shouldn't be in the interrupt handler. It
    * also starts the status_timer. We only execute this function when an
    * interrupt occurs, either the start of the end of the race.
    void racetimer_do_tasklet(unsigned long unused)
    switch (state) {
    case STATE_Timing: /* got into this state from racetimer_interrupt */
    status_timer.expires = jiffies + HZ; /* 1 second intervals */
    add_timer(&status_timer); /* kicks off the first timer */
    printk(KERN_INFO "RaceTimer: Start %s %9i.%06i\n",racernumber,
    (int) starttime.tv_sec, (int) starttime.tv_usec);
    case STATE_Done: /* got into this state from racetimer_interrupt */
    printk(KERN_INFO "RaceTimer: Finish %s %9i.%06i\n",racernumber,
    (int) finishtime.tv_sec, (int) finishtime.tv_usec);

    * This macro actually declares the tasklet and associates it handler
    * racetimer_do_tasklet
    DECLARE_TASKLET(racetimer_tasklet, racetimer_do_tasklet, 0);

    /* racetimer_interrupt
    * Here's the interrupt handler (top-half). It timestamps the race start and
    * finish, changes the state and schedules the bottom half tasklet.
    void racetimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
    switch (state) {
    case STATE_Set:
    state = STATE_Timing; /* change state because now we're racing */
    case STATE_Timing:
    state = STATE_Done; /* change state because race is over */

    /* proc_read_racer
    * This function returns the racer number if the user does a read on
    * /proc/trailblazer/racernumber
    static int proc_read_racer(char *page, char **start, off_t off,
    int count, int *eof, void *data)
    int len;

    len = sprintf(page, "%s\n", racernumber);

    return len;

    /* proc_write_racer
    * This function sets the racer number when the user does a write to
    * /proc/trailblazer/racernumber. Writing to racernumber also changes
    * the state to set.
    static int proc_write_racer(struct file *file, const char *buffer,
    unsigned long count, void *data)
    int len;

    if(count > RACERNUMBERLEN) /* array range checking here */
    len = count;

    if(copy_from_user(racernumber, buffer, len)) {
    return -EFAULT;

    racernumber[len] = '\0'; /* NULL terminate */

    state = STATE_Set; /* change the state, get set for a new race */

    outb(STATUSLED, SPPDATAPORT); /* turn on status LED, solid on means ready */

    return len;

    /* proc_read_racestatus
    * This function returns the state, R, S, T, or D when user reads from
    * /proc/trailblazer/racestatus
    static int proc_read_racestatus(char *page, char **start, off_t off,
    int count, int *eof, void *data)
    int len;

    len = sprintf(page, "%c\n", state);
    return len;


    /* proc_read_racetime
    * This function returns the current or last race time.
    * do_gettimeofday fills the timeval with current seconds and microseconds.
    * Splitting the time in this way requires a little math because the
    * microseconds value is an integer not fraction, (321423 not .321423) So
    * we do a little fixup below if the microseconds differential requires a
    * carry from the seconds value
    static int proc_read_racetime(char *page, char **start, off_t off,
    int count, int *eof, void *data)
    int len;
    long raceseconds, raceuseconds;
    struct timeval currenttime;

    switch (state) {
    case STATE_Ready:
    raceseconds = 0;
    raceuseconds = 0;
    case STATE_Set:
    raceseconds = 0;
    raceuseconds = 0;
    case STATE_Timing: /* we're racing, give 'em the race time */
    raceseconds = currenttime.tv_sec - starttime.tv_sec;
    raceuseconds = currenttime.tv_usec - starttime.tv_usec;
    case STATE_Done: /* race is over, give 'em the race time */
    raceseconds = finishtime.tv_sec - starttime.tv_sec;
    raceuseconds = finishtime.tv_usec - starttime.tv_usec;

    /* need a little fixup here because tv_sec and tv_usec are individual longs */
    if (raceuseconds < 0) {
    raceuseconds += 1000000;

    len = sprintf(page,"%i.%06i\n", raceseconds, raceuseconds);

    return len;

    static int __init init_racetimer(void)
    int rv = 0;

    /* create trailblazer directory */
    tb_dir = proc_mkdir("trailblazer", NULL);
    if(tb_dir == NULL) {
    return -ENOMEM;
    tb_dir->owner = THIS_MODULE;

    /* create racer file */
    racer_file = create_proc_entry("racer", 0666, tb_dir);
    if(racer_file == NULL) {
    rv = -ENOMEM;
    goto no_racer;

    racer_file->data = NULL;
    racer_file->read_proc = &proc_read_racer;
    racer_file->write_proc = &proc_write_racer;
    racer_file->owner = THIS_MODULE;

    /* create racestatus file */
    racestatus_file = create_proc_entry("racestatus", 0444, tb_dir);
    if(racestatus_file == NULL) {
    rv = -ENOMEM;
    goto no_racestatus;

    racestatus_file->data = NULL;
    racestatus_file->read_proc = &proc_read_racestatus;
    racestatus_file->write_proc = NULL;
    racestatus_file->owner = THIS_MODULE;

    /* create racetime file */
    racetime_file = create_proc_entry("racetime", 0444, tb_dir);
    if(racestatus_file == NULL) {
    rv = -ENOMEM;
    goto no_racertime;

    racetime_file->data = NULL;
    racetime_file->read_proc = &proc_read_racetime;
    racetime_file->write_proc = NULL;
    racetime_file->owner = THIS_MODULE;

    /* get into reset state */
    state = STATE_Ready;

    /* turn off the status LED */
    outb(0x00, SPPDATAPORT);

    /* Start with a default racer, old number 0 */

    /* request the interrupt, use SA_INTERRUPT to disable other interrupts
    * while we're running
    rv = request_irq(INTERRUPT, racetimer_interrupt, SA_INTERRUPT,
    if ( rv ) {
    printk("Can't get interrupt %d\n", INTERRUPT);
    goto no_interrupt;

    /* initialize the status timer but don't start it with add_timer(),
    * let someone else do that */
    status_timer.function = status_timer_timed_out;
    status_timer.data = (unsigned long)&state;

    /* enable parallel port interrupt reporting */

    /* everything OK */
    printk(KERN_INFO "%s %s initialized\n",MODULE_NAME, MODULE_VERSION);
    return 0;

    /* clean up /proc directory if we got a error along the way */
    remove_proc_entry("racetime", tb_dir);
    remove_proc_entry("racestatus", tb_dir);
    remove_proc_entry("racer", tb_dir);
    remove_proc_entry("trailblazer", NULL);

    static void __exit cleanup_racetimer(void)
    /* turn off the status LED */
    outb(0x00, SPPDATAPORT);

    /* remove the timer */
    /* be careful here, if the module is removed and a timer remains
    * in the kernel timer list, the kernel will fault when executing
    * the timer's handler (because the handler doesn't exist anymore, you
    * just removed it from memory.) Force the state to done. Then
    * use del_timer_sync, which waits for timer execution completion
    * to occur before deleting the timer. Forcing the state to done tells
    * timer handler status_timer_timed_out to not reschedule the timer.
    state = STATE_Done;

    /* disable parallel port interrupt reporting */

    /* free the interrupt */

    /* remove the /proc entries */
    remove_proc_entry("racetime", tb_dir);
    remove_proc_entry("racestatus", tb_dir);
    remove_proc_entry("racer", tb_dir);
    remove_proc_entry("trailblazer", NULL);

    printk(KERN_INFO "%s %s removed\n", MODULE_NAME, MODULE_VERSION);


    MODULE_AUTHOR("Craig Hollabaugh");
    MODULE_DESCRIPTION("racetimer proc module");


  • More Stories By Maureen O'Gara

    Maureen O'Gara the most read technology reporter for the past 20 years, is the Cloud Computing and Virtualization News Desk editor of SYS-CON Media. She is the publisher of famous "Billygrams" and the editor-in-chief of "Client/Server News" for more than a decade. One of the most respected technology reporters in the business, Maureen can be reached by email at maureen(at)sys-con.com or paperboy(at)g2news.com, and by phone at 516 759-7025. Twitter: @MaureenOGara

    Comments (0)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

    IoT & Smart Cities Stories
    Digital Transformation: Preparing Cloud & IoT Security for the Age of Artificial Intelligence. As automation and artificial intelligence (AI) power solution development and delivery, many businesses need to build backend cloud capabilities. Well-poised organizations, marketing smart devices with AI and BlockChain capabilities prepare to refine compliance and regulatory capabilities in 2018. Volumes of health, financial, technical and privacy data, along with tightening compliance requirements by...
    We are seeing a major migration of enterprises applications to the cloud. As cloud and business use of real time applications accelerate, legacy networks are no longer able to architecturally support cloud adoption and deliver the performance and security required by highly distributed enterprises. These outdated solutions have become more costly and complicated to implement, install, manage, and maintain.SD-WAN offers unlimited capabilities for accessing the benefits of the cloud and Internet. ...
    Discussions of cloud computing have evolved in recent years from a focus on specific types of cloud, to a world of hybrid cloud, and to a world dominated by the APIs that make today's multi-cloud environments and hybrid clouds possible. In this Power Panel at 17th Cloud Expo, moderated by Conference Chair Roger Strukhoff, panelists addressed the importance of customers being able to use the specific technologies they need, through environments and ecosystems that expose their APIs to make true ...
    Business professionals no longer wonder if they'll migrate to the cloud; it's now a matter of when. The cloud environment has proved to be a major force in transitioning to an agile business model that enables quick decisions and fast implementation that solidify customer relationships. And when the cloud is combined with the power of cognitive computing, it drives innovation and transformation that achieves astounding competitive advantage.
    DXWorldEXPO LLC announced today that "IoT Now" was named media sponsor of CloudEXPO | DXWorldEXPO 2018 New York, which will take place on November 11-13, 2018 in New York City, NY. IoT Now explores the evolving opportunities and challenges facing CSPs, and it passes on some lessons learned from those who have taken the first steps in next-gen IoT services.
    "Space Monkey by Vivent Smart Home is a product that is a distributed cloud-based edge storage network. Vivent Smart Home, our parent company, is a smart home provider that places a lot of hard drives across homes in North America," explained JT Olds, Director of Engineering, and Brandon Crowfeather, Product Manager, at Vivint Smart Home, in this SYS-CON.tv interview at @ThingsExpo, held Oct 31 – Nov 2, 2017, at the Santa Clara Convention Center in Santa Clara, CA.
    In an era of historic innovation fueled by unprecedented access to data and technology, the low cost and risk of entering new markets has leveled the playing field for business. Today, any ambitious innovator can easily introduce a new application or product that can reinvent business models and transform the client experience. In their Day 2 Keynote at 19th Cloud Expo, Mercer Rowe, IBM Vice President of Strategic Alliances, and Raejeanne Skillern, Intel Vice President of Data Center Group and G...
    The current age of digital transformation means that IT organizations must adapt their toolset to cover all digital experiences, beyond just the end users’. Today’s businesses can no longer focus solely on the digital interactions they manage with employees or customers; they must now contend with non-traditional factors. Whether it's the power of brand to make or break a company, the need to monitor across all locations 24/7, or the ability to proactively resolve issues, companies must adapt to...
    DXWorldEXPO LLC announced today that ICC-USA, a computer systems integrator and server manufacturing company focused on developing products and product appliances, will exhibit at the 22nd International CloudEXPO | DXWorldEXPO. DXWordEXPO New York 2018, colocated with CloudEXPO New York 2018 will be held November 11-13, 2018, in New York City. ICC is a computer systems integrator and server manufacturing company focused on developing products and product appliances to meet a wide range of ...
    René Bostic is the Technical VP of the IBM Cloud Unit in North America. Enjoying her career with IBM during the modern millennial technological era, she is an expert in cloud computing, DevOps and emerging cloud technologies such as Blockchain. Her strengths and core competencies include a proven record of accomplishments in consensus building at all levels to assess, plan, and implement enterprise and cloud computing solutions. René is a member of the Society of Women Engineers (SWE) and a m...